我也遇到了同样的问题,并去源代码寻找适合我的解决方案。在我看来,Session 类通常存在各种问题。
- 它会在构造函数中初始化默认的 HTTPAdapter,并在将另一个安装到“http”或“https”时泄漏它。
- HTTPAdapter 实现维护了连接池,我认为它不是在每个 Session 对象实例化上创建的。
- Session 关闭 HTTPAdapter,因此您不能在不同的 Session 实例之间重用连接池。
- 根据各种讨论,会话类似乎不是线程安全的。
- HTTPAdapter 在内部使用 urlib3.PoolManager。而且我在源代码中没有发现任何与线程安全相关的明显问题,所以我宁愿相信文档,它说 urlib3 是线程安全的。
作为上面列表的结论,我没有找到比覆盖 Session 类更好的东西
class HttpSession(Session):
def __init__(self, adapter: HTTPAdapter):
self.headers = default_headers()
self.auth = None
self.proxies = {}
self.hooks = default_hooks()
self.params = {}
self.stream = False
self.verify = True
self.cert = None
self.max_redirects = DEFAULT_REDIRECT_LIMIT
self.trust_env = True
self.cookies = cookiejar_from_dict({})
self.adapters = OrderedDict()
self.mount('https://', adapter)
self.mount('http://', adapter)
def close(self) -> None:
pass
并创建连接工厂,如:
class HttpSessionFactory:
def __init__(self,
pool_max_size: int = DEFAULT_CONNECTION_POOL_MAX_SIZE,
retry: Retry = DEFAULT_RETRY_POLICY):
self.__http_adapter = HTTPAdapter(pool_maxsize=pool_max_size, max_retries=retry)
def session(self) -> Session:
return HttpSession(self.__http_adapter)
def close(self):
self.__http_adapter.close()
最后,在我可以写的代码的某个地方:
with self.__session_factory.session() as session:
response = session.get(request_url)
我所有的会话实例都将重用同一个连接池。最后,当应用程序停止时,我可以关闭 HttpSessionFactory。希望这会对某人有所帮助。