bigywater.tech
Scrapy · 50

Request.priority:数值怎么影响出队顺序

priority 到底怎么影响请求的先后?能填什么值?并发高了还有效吗?高优先级请求会不会把低优先级的“饿死”?这篇用能记录到达顺序的服务器逐项量。

TypeError
给 Request 传浮点、字符串或 None 作 priority 的结果
0 → 133
并发从 1 到 60 时,服务器收到顺序里的逆序对数(出队顺序本身仍按优先级)
交替
链式产生的高优先级请求与排队的低优先级请求的出队关系

取值

实测 · 本机执行输出
  构造时报错的:[{'i': 4, 'p': '2.5', 'exc': 'TypeError: Request priority not an integer: 2.5'}, {'i': 6, 'p': "'7'", 'exc': "TypeError: Request priority not an integer: '7'"}, {'i': 7, 'p': 'None', 'exc': 'TypeError: Request priority not an integer: None'}];服务器收到的顺序(r<产生序号>):['r3', 'r1', 'r5', 'r0', 'r2'];finish_reason=finished;spider_exceptions=0
  对应关系:r0=0, r1=5, r2=-5, r3=10**30, r4=2.5(浮点), r5=True, r6='7'(字符串), r7=None
  日志里的错误:[]

priority 只能是整数(bool 算整数),负数、很大的整数都可以;其它类型在构造 Request 时就抛 TypeError。

只管出队

实测 · 本机执行输出
   CONCURRENT_REQUESTS      逆序对数   服务器收到的优先级序列(前 24 个)
                     1         0   [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 6, 6, 6, 6]
                     4         0   [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 6, 6, 6, 6]
                    16         2   [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 6, 6, 6]
                    60       133   [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 6, 8, 6, 7, 6, 8, 6, 6, 3]

优先级决定调度器先取哪个请求,不保证请求先到达服务器或先完成;并发越高,到达顺序越不受控。

只比较队列里的

实测 · 本机执行输出
  (a) 高优先级链(hi0 → hi1 → … → hi9,每个在上一个响应之后才产生):服务器收到 ['hi0', 'low9', 'hi1', 'low8', 'hi2', 'low7', 'hi3', 'low6', 'hi4', 'low5', 'hi5', 'low4', 'hi6', 'low3', 'hi7', 'low2', 'hi8', 'low1', 'hi9', 'low0']
  (b) 10 个高优先级请求和 10 个低优先级请求同时排队:服务器收到 ['hi9', 'hi8', 'hi7', 'hi6', 'hi5', 'hi4', 'hi3', 'hi2', 'hi1', 'hi0', 'low9', 'low8', 'low7', 'low6', 'low5', 'low4', 'low3', 'low2', 'low1', 'low0']

每次出队只在已有的请求里挑优先级最高的。高优先级请求如果还没产生,就轮到低优先级的;只有高优先级请求一直排在队里,低优先级的才会等待。

分步演示

请求优先级
本步的对象

    本文用到的工具与边界

    • 本机 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,数字每次运行会有小幅抖动。种子页的回调里一次产生所有请求,保证它们同时在队列里再出队;到达顺序来自本机线程服务器的日志,并发较高时同时发出的请求到达顺序有竞争(逆序对数每次运行不同)
    • 没有验证:Request.priority 与 DownloaderAwarePriorityQueue 多域名的组合(见调度队列那一篇:优先级只在域名内有效);priority 在 JOBDIR 磁盘队列里的持久化;RETRY_PRIORITY_ADJUST、REDIRECT_PRIORITY_ADJUST 与 DEPTH_PRIORITY 叠加的最终值;优先级取值的上下限(Python 整数无上限,磁盘队列的目录名用优先级,没有测极大值)
    京ICP备2026067502号-1京公网安备11010502063487号