每个域名一个下载槽,延迟和并发都按槽算。槽的名字是怎么取的?能不能用 meta 把几个域名合并成一个槽、或者把一个域名拆开?空闲的槽什么时候被回收?这篇一项项量出来。
[默认]
http://a.com/x meta={} → 槽名 'a.com'
https://a.com:8443/y meta={} → 槽名 'a.com'
http://www.a.com/z meta={} → 槽名 'www.a.com'
http://A.COM/p meta={} → 槽名 'a.com'
http://[::1]:8080/ meta={} → 槽名 '::1'
http://a.com/x meta={'download_slot': 'myslot'} → 槽名 'myslot'
http://localhost:端口/h meta={} → 槽名 'localhost'
http://127.0.0.1:端口/h meta={} → 槽名 '127.0.0.1'
[CONCURRENT_REQUESTS_PER_IP=2(需要 ScrapyPriorityQueue)]
http://a.com/x meta={} → 槽名 'a.com'
https://a.com:8443/y meta={} → 槽名 'a.com'
http://www.a.com/z meta={} → 槽名 'www.a.com'
http://A.COM/p meta={} → 槽名 'a.com'
http://[::1]:8080/ meta={} → 槽名 '::1'
http://a.com/x meta={'download_slot': 'myslot'} → 槽名 'myslot'
http://localhost:端口/h meta={} → 槽名 '127.0.0.1'
http://127.0.0.1:端口/h meta={} → 槽名 '127.0.0.1'Downloader.get_slot_key 先看 request.meta["download_slot"],没有就取 URL 的主机名;设了 CONCURRENT_REQUESTS_PER_IP 则换成解析出的 IP。
(a) 两个主机名各 20 个,默认槽:共 40 个请求,总耗时 4.0 s (b) 同上,全部 meta download_slot="shared":共 40 个请求,总耗时 7.9 s (c) 一个主机名 40 个,按奇偶拆成槽 even / odd:共 40 个请求,总耗时 3.8 s 理想值:(a) 20×0.2 = 4.0 s(两个槽并行);(b) 40×0.2 = 8.0 s(一个槽);(c) 20×0.2 = 4.0 s(两个槽并行)
延迟(和并发限制)只在同一个槽内生效。想让多个域名共享礼貌间隔,就用 meta 指到同一个槽;想把同一个域名当作几个独立的下载通道,就拆成多个槽。
DOWNLOAD_SLOTS={"api": {"delay": 0.05}},20 个请求都指到槽 api:间隔中位数 51 ms,总耗时 1.0 s(全局 DOWNLOAD_DELAY 是 0.2,若不生效应是 4.0 s)按槽名给 delay、concurrency、jitter 设置覆盖值,槽名可以是主机名,也可以是自定义的。
0 s 槽 ['127.0.0.1', 'localhost']
10 s 槽 ['127.0.0.1', 'localhost']
20 s 槽 ['127.0.0.1', 'localhost']
30 s 槽 ['127.0.0.1', 'localhost']
40 s 槽 ['127.0.0.1', 'localhost']
50 s 槽 ['127.0.0.1', 'localhost']
60 s 槽 ['localhost']
70 s 槽 ['localhost']
80 s 槽 ['localhost']
90 s 槽 ['localhost']
100 s 槽 ['localhost']
110 s 槽 ['localhost']
120 s 槽 []每 60 秒检查一次,回收没有活动请求且最后一次放行超过 60 秒的槽。回收是“新建槽、重新计时”的意思,不影响正确性。