什么时候应将单个会话实例用于请求?

时间:2018-11-12 14:06:36

标签: python python-requests aiohttp

来自aiohttp文档:

  

[aiohttp.ClientSession]封装了一个连接池(连接器实例),并且默认情况下支持keepalive。 除非您在应用程序的生存期内连接到大量未知的不同服务器,否则建议您在应用程序的生存期内使用单个会话以受益于连接池。

我几乎总是采用对任何大小或容器的URL保留单个ClientSession实例(启用cookie和自定义连接器/适配器*)的做法,无论这些URL的种类繁多或数量多少其中有。我想知道这种方法是否有缺点。

我希望对实践中“大型,未知数量的不同服务器”的构成有一个更细致的上下文定义。下列情况下的最佳做法是什么? ClientSession是否应该专用于每个netloc,而不是整个集合的单个实例?**是否使用单个客户端会话的决定是否仅由响应时间决定?

通常情况下,我有很多端点。每个批次的netloc是同质的,但是批次之间的netloc是不同的。例如,

urls = {
    'https://aiohttp.readthedocs.io/en/stable/index.html',
    'https://aiohttp.readthedocs.io/en/stable/client_reference.html',
    'https://aiohttp.readthedocs.io/en/stable/web_advanced.html#aiohttp-web-middlewares',

    'https://www.thesaurus.com/',
    'https://www.thesaurus.com/browse/encapsulate',
    'https://www.thesaurus.com/browse/connection?s=t',

    'https://httpbin.org/',
    'https://httpbin.org/#/HTTP_Methods',
    'https://httpbin.org/status/200'
}

要在上面加上一个数字,实际上每批的长度可能为25-50。


*我现在要做的是通过将连接器实例传递到ClientSessionaiohttp.TCPConnector(limit_per_host=10))来限制对任何单个主机的打开连接。

**具体来说,{'www.thesaurus.com', 'aiohttp.readthedocs.io', 'httpbin.org'},即set(urllib.parse.urlsplit(u).netloc for u in urls)

1 个答案:

答案 0 :(得分:2)

您希望在使用专用会话时使用自己的连接器

  1. 您要为一组连接自定义连接器参数(例如,更改每个主机的限制,或更改SSL配置,或设置不同的超时)。
  2. 您将经历默认的100个连接限制,此时与现有主机的缓存连接被回收的可能性与仍处于打开状态的缓存一样。

后一种情况是文档所暗示的。假设您要连接的唯一主机数量更多(唯一主机是主机名,端口号以及是否使用SSL的唯一组合),但是正在与其中的 some 个主机联系比其他人更多。如果“大数字”> 100,则您可能必须继续为之前已连接的“频繁”主机打开新连接,因为池必须关闭它们才能为当前不在的主机创建连接游泳池。那会影响性能。

但是,如果您为“常用”主机创建了一个单独的池,则可以使这些主机连接的打开时间更长。他们不必与所有那些不经常使用的主机连接竞争来自“通用”池的免费连接。

在aiohttp中,您通过使用单独的会话来创建单独的池,然后必须定义逻辑以选择用于给定请求的会话。

为进行比较,requests库(一个同步HTTP API)对它的处理方式略有不同,您可以在其中register separate transport adapters per url prefix