下载很快、处理很慢的时候,Scrapy 会不会把所有响应都堆在内存里?背压在哪里发生、阈值是多少、小响应怎么计?这篇用故意拖慢的回调,量出不同上限下滞留的响应数、内存和耗时。
SCRAPER_SLOT_MAX_ACTIVE_SIZE = 1,000,000 峰值 active_size 2,400,312 字节;同时滞留的响应 24 个;进程峰值 RSS 99.5 MiB;总耗时 11.1 s 默认 5,000,000 峰值 active_size 6,500,845 字节;同时滞留的响应 65 个;进程峰值 RSS 118.1 MiB;总耗时 3.8 s SCRAPER_SLOT_MAX_ACTIVE_SIZE = 20,000,000 峰值 active_size 21,202,756 字节;同时滞留的响应 212 个;进程峰值 RSS 170.8 MiB;总耗时 1.3 s = 100,000,000(基本不限) 峰值 active_size 40,005,200 字节;同时滞留的响应 400 个;进程峰值 RSS 239.4 MiB;总耗时 0.9 s
响应进入 scraper 时 active_size 加上它的大小(至少 1024),回调、pipeline 处理完才减掉;一超过 SCRAPER_SLOT_MAX_ACTIVE_SIZE,引擎的 needs_backout() 为真,不再取调度器里的请求。上限越大滞留的响应越多、内存越高、总耗时越短。
默认设置,回调不等待 峰值 active_size 2,500,325 字节;同时滞留的响应 25 个;进程峰值 RSS 98.2 MiB;总耗时 0.4 s
只有处理比下载慢才会堆积;回调、pipeline 都很快时,滞留量基本等于并发数,背压没有效果。
默认 SCRAPER_SLOT_MAX_ACTIVE_SIZE = 5,000,000:峰值 active_size 1,047,552 = 1023 × 1024 + 0;同时滞留的响应 1023 个;进程峰值 RSS 258.7 MiB;总耗时 11.0 s SCRAPER_SLOT_MAX_ACTIVE_SIZE = 500,000:峰值 active_size 602,112 = 588 × 1024 + 0;同时滞留的响应 588 个;进程峰值 RSS 198.2 MiB;总耗时 13.0 s 500,000 ÷ 1024 = 488 个;在途下载最多 100 个,所以峰值会超过一点
很小的响应按 1024 字节计费,所以大量小响应时按个数而不是按字节数限制。