bigywater.tech
Scrapy · 18

AutoThrottle:延迟怎么根据响应时间调整

AutoThrottle 声称“根据服务器的响应时间自动调整延迟”。它具体怎么调?变慢变快各多快?404 会不会骗过它?能不能保证并发?这篇用能改变延迟的服务器逐项实测,并对照 2.19 里它的几行源码。

≈ 8 个响应
延迟收敛到 latency ÷ N 附近所需的响应数(每次走一半)
25 vs 506 ms
后面都是快速 200 与快速 404 时,最终的 delay
2 / 3 / 7
目标并发 1 / 2 / 4 时服务器上实际的同时处理峰值

更新规则

实测 · 本机执行输出
  TARGET_CONCURRENCY=1:delay 轨迹(ms)= [501, 354, 279, 241, 224, 212, 207, 205, 207, 205, 207, 206, 205, 203] … [206, 204, 203];最终 203 ms(目标 latency/1 = 200 ms);服务器并发峰值 2;总耗时 10.8 s
  TARGET_CONCURRENCY=2:delay 轨迹(ms)= [500, 301, 201, 152, 126, 114, 108, 104, 103, 102, 102, 102, 102, 101] … [102, 102, 101];最终 101 ms(目标 latency/2 = 100 ms);服务器并发峰值 2;总耗时 7.5 s

每个响应下载完成后,AutoThrottle 取目标延迟 latency / AUTOTHROTTLE_TARGET_CONCURRENCY,新延迟 = max(目标, (旧延迟 + 目标)/2),并夹在 DOWNLOAD_DELAY 与 AUTOTHROTTLE_MAX_DELAY 之间。

变慢与变快

实测 · 本机执行输出
  delay 轨迹(ms):
      50  105  103  104  104  103  105  105  103  106  107  105  105  103  103
     105  803  803  803  805  807  805  808  806  804  803  806  803  803  802
     802  454  278  192  149  127  117  112  107  106  106  106  103  105  105
     105
  变慢时(第 16~30 个)最高 808 ms;变快后(第 31 个起)delay 每次约折半往下降:[802, 454, 278, 192, 149, 127];服务器并发峰值 7

变慢时由于取 max,延迟一步跳到目标;变快时每个响应只走一半,所以收敛比升高慢。

非 200 响应

实测 · 本机执行输出
  后 20 个返回 200:前 10 个之后 delay = 504 ms;最后 delay = 25 ms;后 20 个的轨迹 [264, 502, 265, 145, 83, 55] …
  后 20 个返回 404:前 10 个之后 delay = 507 ms;最后 delay = 506 ms;后 20 个的轨迹 [506, 506, 506, 506, 506, 506] …

状态码不是 200 且新延迟比旧延迟小时,不调整:避免错误页(又小又快)诱导放松限速。

上下限

实测 · 本机执行输出
  MAX_DELAY=60(默认):delay 轨迹(ms)= [50, 2002, 2002, 2003]
  MAX_DELAY=0.5:delay 轨迹(ms)= [50, 500, 500, 500]
  服务器延迟 0.05 s、DOWNLOAD_DELAY=0.3(最小值):delay 轨迹(ms)= [300, 300, 300, 300, 300, 300] … [300, 300](理想值 50 ms 被抬到 300)

DOWNLOAD_DELAY 是最小延迟,AUTOTHROTTLE_MAX_DELAY 是上限(默认 60 秒),AUTOTHROTTLE_START_DELAY 是起点。

不保证并发

实测 · 本机执行输出
  TARGET_CONCURRENCY   最终 delay ms       服务器并发峰值     总耗时 s
                   1           406             2      20.1
                   2           202             3      10.3
                   4           101             7       5.0

AutoThrottle 只改延迟,不限制并发;默认的 ±50% 抖动和调整的滞后会让实际并发超过 TARGET_CONCURRENCY。

排除个别请求

实测 · 本机执行输出
  服务器收到 20 个请求(后 10 个各耗时 1.0 s),总耗时 3.7 s;debug 行只有 11 条(seed + 前 10 个,带 meta 的不输出);delay 轨迹(ms)= [50, 102, 103, 106, 103, 102, 102, 106, 106, 103, 105]

给请求加 meta["autothrottle_dont_adjust_delay"] = True,它的响应不参与调整。

分步演示

AutoThrottle
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.8 / Scrapy 2.19.0 / Twisted 26.4.0 / lxml 6.1.3 / parsel 1.12.1(临时虚拟环境);所有请求只发给本机自己起的测试服务器(127.0.0.1,端口 9960 以上,不访问任何真实网站);服务器可以按实验需要制造延迟、重定向、压缩、断连等行为,并记录收到的原始请求;每个实验在临时目录里新建 Scrapy 项目或单文件 spider,命令输出来自真实的 scrapy 进程;计时用 time.perf_counter,数字每次运行会有小幅抖动。服务器按到达顺序决定每个请求的延迟和状态码;AUTOTHROTTLE_DEBUG = 1 的日志行解析出每个响应之后槽的 delay;请求用先进先出队列保证顺序
    • 没有验证:多个域名各自的槽独立调整(只测了一个槽);与 CONCURRENT_REQUESTS_PER_DOMAIN 的组合(受上一篇的发现影响,这里没有靠它限制并发);抖动关掉(DOWNLOAD_DELAY_JITTER = 0)时并发是否贴近目标;真实服务器上 latency 的抖动对收敛的影响;download_latency 的含义(Twisted 与 aiohttp 处理器是否一致)
    京ICP备2026067502号-1京公网安备11010502063487号