我可以更改Python的"请求"模块的连接池大小吗?

Ski*_*man 41 python multithreading request python-requests

(编辑:也许这个错误意味着我错了.这是否表示我的CLIENT的连接池已满?或者SERVER的连接池已满,这是我的客户端给出的错误?)

我试图http使用python threadingrequests模块同时发出大量请求.我在日志中看到这个错误:

WARNING:requests.packages.urllib3.connectionpool:HttpConnectionPool is full, discarding connection:
Run Code Online (Sandbox Code Playgroud)

如何增加请求的连接池大小?

小智 83

这应该做的伎俩:

import requests
sess = requests.Session()
adapter = requests.adapters.HTTPAdapter(pool_connections=100, pool_maxsize=100)
sess.mount('http://', adapter)
resp = sess.get("/mypage")
Run Code Online (Sandbox Code Playgroud)

  • 这适合我.它应该被标记为正确的答案. (5认同)
  • 请注意,“(pool_connections=100, pool_maxsize=100)”是非常高的值。您应该根据您的实际场景定制它们,考虑您要连接的不同主机的数量以及您正在使用的工作线程的数量。 (3认同)
  • @JohnStrood:一种更合规的方式,不依赖任何“私有”属性,检查给定的 URL 将是 `sess.get_adapter(url).poolmanager.connection_pool_kw['maxsize']`。 (3认同)
  • 这在用 `https` 替换 `http` 后起作用了。另外我认为 `pool_connections` 是不必要的。 (2认同)

Mic*_*arf 19

注意:仅当您无法控制连接池的构造时才使用此解决方案(如@ Jahaja的答案中所述).

问题是urllib3按需创建池.它调用urllib3.connectionpool.HTTPConnectionPool没有参数的类的构造函数.课程已注册urllib3 .poolmanager.pool_classes_by_scheme.诀窍是用具有不同默认参数的类替换类:

def patch_http_connection_pool(**constructor_kwargs):
    """
    This allows to override the default parameters of the 
    HTTPConnectionPool constructor.
    For example, to increase the poolsize to fix problems 
    with "HttpConnectionPool is full, discarding connection"
    call this function with maxsize=16 (or whatever size 
    you want to give to the connection pool)
    """
    from urllib3 import connectionpool, poolmanager

    class MyHTTPConnectionPool(connectionpool.HTTPConnectionPool):
        def __init__(self, *args,**kwargs):
            kwargs.update(constructor_kwargs)
            super(MyHTTPConnectionPool, self).__init__(*args,**kwargs)
    poolmanager.pool_classes_by_scheme['http'] = MyHTTPConnectionPool
Run Code Online (Sandbox Code Playgroud)

然后,您可以调用以设置新的默认参数.确保在建立任何连接之前调用此方法.

patch_http_connection_pool(maxsize=16)
Run Code Online (Sandbox Code Playgroud)

如果使用https连接,则可以创建类似的功能:

def patch_https_connection_pool(**constructor_kwargs):
    """
    This allows to override the default parameters of the
    HTTPConnectionPool constructor.
    For example, to increase the poolsize to fix problems
    with "HttpSConnectionPool is full, discarding connection"
    call this function with maxsize=16 (or whatever size
    you want to give to the connection pool)
    """
    from urllib3 import connectionpool, poolmanager

    class MyHTTPSConnectionPool(connectionpool.HTTPSConnectionPool):
        def __init__(self, *args,**kwargs):
            kwargs.update(constructor_kwargs)
            super(MyHTTPSConnectionPool, self).__init__(*args,**kwargs)
    poolmanager.pool_classes_by_scheme['https'] = MyHTTPSConnectionPool
Run Code Online (Sandbox Code Playgroud)

  • 这取决于具体情况.如果您可以控制创建HTTPAdapter,那么使用构造函数是正确的解决方案.但有些情况下,连接池初始化在某个框架或库中深埋的地方.在这些情况下,您可以修补库或修补连接池构造函数,如上所述. (5认同)
  • 是的,这可能是另一个问题的答案,但这是我在搜索以下内容时发现的问题:“HttpConnectionPool 已满,正在丢弃连接 python”。但是该解决方案对我没有帮助,因为我的连接池是由某个库(在我的情况下为 pyes)创建的。 (2认同)

Mes*_*ion 10

Jahaja\'s 的答案已经为您的问题提供了建议的解决方案,但它没有回答发生了什么,或者正如您所问的,这个错误意味着什么

\n

urllib3官方文档中有一些非常详细的信息,该包requests在幕后使用它来实际执行其请求。以下是您问题的相关部分,添加了我自己的一些注释并省略了代码示例,因为requests有不同的 API:

\n
\n

该类根据需要PoolManager自动处理为每个主机创建实例。ConnectionPool默认情况下,它将保留最多 10 个 ConnectionPool 实例[注意:这是pool_connections在 中requests.adapters.HTTPAdapter(),并且它具有相同的默认值 10]。如果您\xe2\x80\x99向许多不同的主机发出请求,则增加此数字可能会提高性能

\n

但是,请记住,这确实会增加内存和套接字消耗。

\n

类似地,ConnectionPool 类保留一个单独HTTPConnection实例的池。这些连接在单个请求期间使用,并在请求完成时返回到池中。默认情况下,只会保存一个连接以供重复使用[注意:这是pool_maxsize在 中HTTPAdapter(),请求将默认值从 1 更改为 10]。如果您同时向同一主机发出多个请求,则增加此数量可能会提高性能

\n

ConnectionPool 的池化行为与 PoolManager 不同。默认情况下,如果发出新请求并且池中没有空闲连接,则会创建一个新连接。但是,如果存在多个maxsize连接,则不会保存该连接。这意味着 maxsize 并不确定可以向特定主机打开的最大连接数,而只是确定池中保留的最大连接数。但是,如果您指定block=True [注意:可用如pool_block] HTTPAdapter() 则最多可以向特定主机打开 maxsize 连接

\n
\n

鉴于此,这就是您的案例中发生的情况:

\n
    \n
  • 所有提到的池都是客户端池。您(或requests)无法控制任何服务器连接池
  • \n
  • 该警告是关于同一主机HttpConnectionPool的同时连接数,因此您可以增加以匹配您用来消除警告的工作线程/线程数。pool_maxsize
  • \n
  • 请注意requests无论. pool_maxsize如果有 100 个线程,它将打开 100 个连接。但默认值下,池中只会保留 10 个以供以后重用,而 90 个将在完成请求后被丢弃。
  • \n
  • 因此,较大的主机通过重用连接pool_maxsize来提高性能,而不是通过增加并发性。
  • \n
  • 如果您正在处理多个主机,那么您可能会进行更改pool_connections。默认值已经是 10,因此如果您的所有请求都发送到同一目标主机,则增加它不会对性能产生任何影响(但会增加使用的资源,如上面文档中所述)
  • \n
\n