bigywater.tech
爬虫工程 · 19

aiohttp 的 limit 与 limit_per_host

aiohttp 把并发限制放在 TCPConnector 里,但 limit 和 limit_per_host 到底各管什么、两个同时设怎么办、几个会话一起跑又怎样,文档里一两句话很难说清。这篇在本机用多台服务器和多个主机名把它们逐一量出来。

100
aiohttp 默认对单个站点允许同时开的连接数上限(limit=100,limit_per_host=0)
20 对 5
limit_per_host=5 时,用 4 个不同主机名访问同一台服务器,服务器实际看到的并发峰值(同一主机名是 5)
30
3 个 ClientSession 各 limit=10 同时运行时的服务器并发峰值

默认值

实测 · 本机执行输出
  aiohttp.TCPConnector() 默认 limit=100,limit_per_host=0(0 表示不限)

默认 limit=100、limit_per_host=0。直接用默认值的爬虫,对目标站点最高会同时开 100 条连接;这个数字对某个站点是否合适,取决于那个站点,本文没有拿任何真实站点测它的承受能力。

单个主机

实测 · 本机执行输出
  默认(limit=100,limit_per_host=0):服务器同时在处理的峰值 100,累计连接数 100,总耗时 245 ms
  limit=0(不限):服务器同时在处理的峰值 200,累计连接数 200,总耗时 158 ms
  limit=20:服务器同时在处理的峰值 20,累计连接数 20,总耗时 1091 ms
  limit_per_host=5:服务器同时在处理的峰值 5,累计连接数 5,总耗时 4231 ms

只有一个目标主机时,limit 和 limit_per_host 效果一样:服务器看到的并发峰值就是设定值,总耗时接近 请求数 / 上限 × 单次耗时。limit=0 表示不限制,200 个请求会同时发出。

多个主机

实测 · 本机执行输出
  limit=30:三台服务器各自的并发峰值 [14, 24, 14],三台合起来同时在处理的峰值 30,总耗时 1080 ms
  limit=0,limit_per_host=5:三台服务器各自的并发峰值 [5, 5, 5],三台合起来同时在处理的峰值 15,总耗时 3163 ms
  limit=30,limit_per_host=5:三台服务器各自的并发峰值 [5, 5, 5],三台合起来同时在处理的峰值 15,总耗时 3183 ms

limit 限制所有主机合计的连接数,各主机之间分配不均(实测 [14, 24, 14]);limit_per_host 限制每个主机。两个同时设置时,更紧的那个起作用。

主机的定义

实测 · 本机执行输出
  用同一个主机名(127.0.0.1)访问,limit_per_host=5:服务器同时处理的峰值 5,4270 ms
  用 4 个不同主机名(都解析到同一台服务器)访问,limit_per_host=5:服务器同时处理的峰值 20,1523 ms

limit_per_host 按请求里的主机名和端口分组,不关心它们是不是同一台服务器。用 4 个域名访问同一台服务器,服务器实际看到的并发是 4 × 5 = 20。

连接器是会话级的

实测 · 本机执行输出
  1 个 ClientSession,每个 limit=10,各发 100 个请求:服务器同时处理的峰值 10,总耗时 1087 ms
  3 个 ClientSession,每个 limit=10,各发 100 个请求:服务器同时处理的峰值 30,总耗时 1102 ms
  同样 300 个请求但共用 1 个 ClientSession(limit=10):服务器同时处理的峰值 10,总耗时 3216 ms

上限属于 TCPConnector,每个 ClientSession 默认有自己的连接器,所以几个会话同时跑,总并发是它们的上限之和。想要全局的上限,会话要共用,或者在外面再套一层 Semaphore。

分步演示

TCPConnector 的 limit
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.8 / requests 2.34.2 / aiohttp 3.14.3 / lxml 6.1.1(系统 Python);所有请求只发给本机自己起的测试服务器(127.0.0.1,端口 9960 以上,不访问任何真实网站);服务器可以按实验需要制造延迟、断连、压缩、重定向等行为,并记录收到的原始请求;计时用 time.perf_counter,数字每次运行会有小幅抖动。aiohttp 3.14.3;服务器每个请求停 0.1 秒;同时处理的请求峰值由服务器统计,三台服务器的合计峰值用一个带锁的全局计数器统计(各自峰值相加是不对的,因为峰值出现的时刻不同);用 a.test 等主机名时把 getaddrinfo 替换为都解析到 127.0.0.1;每项各测一次,毫秒数仅供参考
    • 没有验证:limit 满了之后排队的先后顺序;排队等待连接是否受 ClientTimeout 的哪一项约束(第 18 篇测到总超时会算上排队时间);keepalive 连接闲置时是否占用 limit 的名额;HTTP/2 下 aiohttp(不支持)与 curl_cffi 的连接数控制;connector 的 limit 在 HTTPS 与代理下的计数方式
    京ICP备2026067502号-1京公网安备11010502063487号