实测 Scrapy 2.19 的调度队列:有 JOBDIR 时 21 个请求全进磁盘队列;priority 大的先出、同优先级默认后进先出;不可序列化的请求退回内存队列(默认无日志)并因“内存先于磁盘”打乱优先级;默认的 DownloaderAwarePriorityQueue 让优先级只在域名内有效,且与 CONCURRENT_REQUESTS_PER_IP 冲突。
服务端流的流控实测:快生产者遇到慢消费者,Send 从 0.4 ms 变成 31 ms 跟着消费者走;不读数据时默认只能先发 195584 字节;调大接收窗口可以多发,窗口选项会关闭动态窗口;被阻塞的 Send 在取消后返回 Canceled;handler 返回后已发的消息仍会送达。
客户端流和双向流的结束语义:CloseSend 在线上是长度 0 的 DATA 帧加 END_STREAM;半关闭后服务端还能继续发;服务端提前结束时客户端 Send 一律返回 io.EOF,状态要靠 Recv 取;只 Send 不 Recv 会在 5 条(1280 KiB)后死锁;忘了 CloseSend 服务端一直等。
实测 Scrapy 2.19 的请求去重:参数顺序、#片段、主机大小写算同一个,:80、末尾 /、http/https、www. 算不同;POST 体逐字节比较、请求头和 meta 默认不参与;requests.seen 每个指纹 22 字节;自己写的 start() 默认不带 dont_filter;100 万个指纹的 set 占 86.6 MB。
实测 dont_filter 何时该用:有环的站点全部 dont_filter=True 会一直转(1 秒 799 个请求),要靠 DEPTH_LIMIT / CLOSESPIDER_* 刹车;重试请求自带 True;重定向沿用原请求的值,重定向到已抓过的 URL 会被去重吃掉,回调不被调用;轮询同一个 URL 必须加。
实测 HTTP/2 流控窗口:吞吐大致等于窗口除以往返时间——RTT 20 ms 时 64 KiB 窗口只有 2.5 MiB/s、4 MiB 窗口 119.5;默认的动态窗口靠 PING 测量 BDP 逐步长大;4 个流共享连接时连接窗口 64 KiB 把总吞吐压到 9.1 MiB/s(4 MiB 时 402.7);小消息不受影响。
实测 gRPC 客户端连接管理:NewClient 惰性建连;pick_first 只连一个地址、round_robin 连全部;默认退避 1 秒起乘 1.6;断开后进入 IDLE 等下一次调用;GracefulStop 发两个 GOAWAY;WithIdleTimeout 让空闲连接回到 IDLE。
实测下载器中间件的调用顺序:process_request 按数字从小到大、process_response 反过来;595 看到 gzip 的 64 字节、585 看到解压后的 2613 字节;process_request 返回 Response 时仍然调用全部 process_response;返回 Request 会重新走一遍中间件链;process_exception 按响应方向调用。
实测 Scrapy 2.19 爬虫中间件:input 从小到大、output 从大到小;input 抛异常直接进 errback 且不算 spider 异常;output 可以过滤请求和 item;process_spider_exception 按 C、B、A 调用,返回可迭代对象即可终止;同步版 process_spider_output 在 2.19 启动即 TypeError。
实测 gRPC keepalive:客户端 Time 有 10 秒下限;服务端默认策略下客户端 PING 到第三个就被 GOAWAY(too_many_pings);对端变成黑洞时有 keepalive 12 秒发现、没有的要等到 deadline;服务端也能探活;PermitWithoutStream 默认 false 时空闲连接不探测。
实测 Scrapy 2.19 的 item pipeline:按数字顺序调用,DropItem 丢弃并计入 item_dropped_count,其它异常只记 ERROR;open_spider / close_spider 并行执行;返回 None 不是丢弃(下一个管道收到 None,仍计入 item_scraped_count);CONCURRENT_ITEMS 1 → 100 让 50 个 await 0.1 s 的 item 从 5.13 s 降到 0.11 s。
实测 ItemLoader:输入处理器每次 add_value 调用、输出处理器只在 load_item 时调用;TakeFirst 取第一个非 None 非空串(0 算有值)、MapCompose 丢 None 并展平列表;Loader 的 字段_in 压过 Field 元数据压过 default;loader_context 传参;None 不收集而 '' 会收集;默认 item 类是 scrapy.Item,未声明字段 KeyError。