初始化请求'Session
时,将创建两个^{
这就是HTTPAdapter
的定义:
class requests.adapters.HTTPAdapter(pool_connections=10, pool_maxsize=10,
max_retries=0, pool_block=False)
虽然我理解pool_maxsize
(池可以保存的会话数)的含义,但我不理解pool_connections
的含义或它的作用。医生说:
Parameters:
pool_connections – The number of urllib3 connection pools to cache.
但是“缓存”是什么意思?使用多个连接池有什么意义?
请求使用urllib3来管理其连接和其他功能。
重新使用连接是保持重复HTTP请求性能的一个重要因素。The urllib3 README explains:
要回答您的问题,“pool_maxsize”是每个主机要保留的连接数(这对于多线程应用程序很有用),而“pool_connections”是要保留的主机池数。例如,如果您连接到100个不同的主机,并且
pool_connections=10
,则只会重新使用最新10个主机的连接。感谢@laike9m提供了现有的问答和文章,但是现有的答案没有提到
pool_maxsize
的微妙之处及其与多线程代码的关系。小结
pool_connections
是一个端点(主机、端口、方案)在给定时间内可以在池中保持活动状态的连接数。如果您想在池中保持最大值为n
的打开TCP连接以便与Session
一起重用,则需要pool_connections=n
。pool_maxsize
实际上与requests
的用户无关,因为pool_block
(inrequests.adapters.HTTPAdapter
)的默认值是False
,而不是True
细节
正如这里正确指出的,
pool_connections
是给定适配器前缀的最大打开连接数。最好通过例子来说明:上面,最大连接数是1;它是
(github.com, 443, https)
。如果要从新的(主机、端口、方案)三元组请求资源,内部的Session
将转储现有连接,为新连接腾出空间:你可以把这个数字调高到
pool_connections=2
,然后在3个不同的主机组合之间循环,你将在游戏中看到相同的东西。(另一件需要注意的事情是,会话将以同样的方式保留和发送cookies。)现在是
pool_maxsize
,它被传递给urllib3.poolmanager.PoolManager
,并最终传递给urllib3.connectionpool.HTTPSConnectionPool
。maxsize的docstring是:顺便说一下,
block=False
是HTTPAdapter
的默认值,即使HTTPConnectionPool
的默认值是True
。这意味着pool_maxsize
对HTTPAdapter
几乎没有影响。此外,} 通过多个URL发出请求:
requests.Session()
是而不是线程安全的;您不应该从多个线程使用相同的session
实例。(请参见here和here)如果您真的想这样做,更安全的方法是将每个线程借给它自己的本地化会话实例,然后使用该会话通过^{我写了一篇关于这个的文章。贴在这里:
请求的秘密:池连接和池最大大小
Requests是Python程序员最著名的Python第三方库之一(如果不是的话)。由于其简单的API和高性能,人们倾向于使用请求,而不是标准库为HTTP请求提供的urllib2。然而,每天使用请求的人可能不知道请求的内部结构,今天我要介绍其中两个:
pool_connections
和pool_maxsize
。让我们从
Session
开始:很简单。您可能知道请求'} 方法吗?
Session
可以持久化cookie。很酷。但是你知道Session
有一个^{没有?实际上,当您initialize a ^{} object 使用此方法时:
有趣的部分来了。如果您阅读了Ian Cordasco的文章Retries in Requests,您应该知道
HTTPAdapter
可以用来提供重试功能。但什么是真正的HTTPAdapter
?引自doc:如果上面的文档让您感到困惑,那么我的解释是:HTTP适配器所做的只是根据目标url为不同的请求提供不同的配置。还记得上面的代码吗?
它用默认参数
pool_connections=10, pool_maxsize=10, max_retries=0, pool_block=False
创建两个HTTPAdapter
对象,并分别挂载到https://
和http://
,这意味着如果您尝试向http://xxx
发送请求,将使用第一个HTTPAdapter()
的配置,第二个HTTPAdapter()
将用于对https://xxx
的请求。在这种情况下,这两种配置是相同的,对http
和https
的请求仍然是分别处理的。我们待会儿再看它是什么意思。正如我所说,本文的主要目的是解释
pool_connections
和pool_maxsize
。首先让我们看看
pool_connections
。昨天我在stackoverflow上提出了一个{a7},因为我不确定我的理解是否正确,答案消除了我的不确定性。众所周知,HTTP是基于TCP协议的。HTTP连接也是一个TCP连接,它由五个值的元组标识:假设您已经与
www.example.com
建立了HTTP/TCP连接,假设服务器支持Keep-Alive
,下一次向www.example.com/a
或www.example.com/b
发送请求时,您可以使用相同的连接,因为这五个值都没有更改。事实上,requests' Session automatically does this for you将尽可能地重用连接。问题是,什么决定了您是否可以重用旧连接?是的,
pool_connections
!我知道,我知道,我也不想带这么多术语,这是最后一个,我保证。为了便于理解,一个连接池对应于一个主机。
下面是一个例子(不相关的行被忽略):
HTTPAdapter(pool_connections=1)
被装载到https://
,这意味着一次只存在一个连接池。在调用s.get('https://www.baidu.com')
之后,缓存的连接池是connectionpool('https://www.baidu.com')
。现在s.get('https://www.zhihu.com')
来了,会话发现它不能使用以前缓存的连接,因为它不是同一个主机(一个连接池对应于一个主机,记得吗?)。因此,会话必须创建一个新的连接池,或者连接(如果您愿意)。由于pool_connections=1
,会话不能同时容纳两个连接池,因此它放弃了原来的connectionpool('https://www.baidu.com')
,保留了新的connectionpool('https://www.zhihu.com')
。下一个get
是相同的。这就是为什么我们在日志中看到三个Starting new HTTPS connection
。如果我们将
pool_connections
设置为2:很好,现在我们只创建了两次连接,节省了一次连接建立时间。
最后,
pool_maxsize
。首先也是最重要的是,只有在多线程环境中使用
Session
时,您才应该关心pool_maxsize
,就像使用相同的Session
从多个线程发出并发请求一样。实际上,} ,这正是我们上面提到的连接池。
pool_maxsize
是初始化urllib3的参数^{HTTPConnectionPool
是指向特定主机的连接集合的容器,而pool_maxsize
是可重用的要保存的连接数。如果您在一个线程中运行代码,则既不可能也不需要创建到同一主机的多个连接,因为请求库被阻塞,因此总是一个接一个地发送HTTP请求。如果有多个线程,情况就不同了。
看到了吗?它为同一个主机建立了两个连接,就像我说的,这只能在多线程环境中发生。 在本例中,我们使用
pool_maxsize=2
创建了一个连接池,并且同时没有超过两个连接,所以这就足够了。 我们可以看到来自t3
和t4
的请求没有创建新的连接,它们重用了旧的连接。如果尺寸不够怎么办?
现在,
pool_maxsize=1
,警告如期而至:我们还可以注意到,由于此池中只能保存一个连接,因此将再次为
t3
或t4
创建新连接。显然这是非常低效的。这就是为什么在urllib3的文档中说:最后但并非最不重要的是,
HTTPAdapter
装载到不同前缀的实例是独立的。上面的代码很容易理解,所以我不解释。
我想就这些了。希望本文能帮助您更好地理解请求。顺便说一下,我创建了一个gisthere,其中包含本文中使用的所有测试代码。下载并播放:)
附录
Session
的mount
方法将确保首先匹配最长的前缀。它的实现非常有趣,所以我把它贴在这里。注意
self.adapters
是一个OrderedDict
。相关问题 更多 >
编程相关推荐