
做爬虫的估计都遇到过这种时候:昨天还跑得好好的任务,今天突然慢到怀疑人生。第一反应基本都是"代理不行了",然后开始骂服务商、准备换套餐、翻新的 IP 池。
我最近在做一个电商价格监控项目,请求量从日均 20 万涨到 80 万之后开始出现明显的耗时抖动。当时的第一反应也是换代理,但把请求耗时按 DNS、TCP、TLS、首字节、传输拆开测了一遍之后发现:一半以上的瓶颈其实落在采集系统内部和目标站的限速策略里,跟代理链路关系不大。
这篇把我完整的排查思路整理了一下,包括当时用极安代理做基线对照的具体数据,希望能帮后面遇到类似问题的人少走弯路。
一句话总结:先分层测量再决定动手方向,比直接换服务商省时间也省钱。
"慢"是症状不是诊断。不同表现指向不同的锅:
症状 | 具体表现 | 大概率在哪 |
|---|---|---|
单请求 TTFB > 3s | time_starttransfer 偏高 | 目标站服务端处理慢或触发限速 |
连接建立 > 500ms | time_connect 高,TLS 也慢 | 代理链路或运营商出口 |
首次 DNS > 200ms、后续正常 | time_namelookup 首次慢,后续为 0 | 采集端没 DNS 缓存 |
并发拉到 50 就卡住 | CPU/带宽都没打满,QPS 不涨 | 连接池、线程模型、GIL |
成功率下降伴随耗时上升 | 4xx/5xx 变多 | 触发风控或 IP 被识别 |
单 IP 用几分钟就慢 | 换 IP 立刻恢复 | 目标站按 IP 限速 |
对号入座只是起点,真正判断责任还得靠下面的分层测量,别靠感觉。
少一样都很难查得清楚。
历史基线。 正常的时候 P50、P95 是多少,DNS/TCP/TLS 各段是多少。没有基线,"变慢"就只是主观感受。我一般让每个采集任务上线时留一份 100–1000 次请求的耗时分布日志,后面对比全靠它。
分层测量脚本。 curl 的 -w 参数最轻量,一条命令把请求拆成五段:
curl -o /dev/null -s -w "\
time_namelookup: %{time_namelookup}\n\
time_connect: %{time_connect}\n\
time_appconnect: %{time_appconnect}\n\
time_starttransfer: %{time_starttransfer}\n\
time_total: %{time_total}\n" \
-x http://代理地址:端口 https://目标站.com读法很直接:
time_namelookuptime_connect - time_namelookuptime_appconnect - time_connecttime_starttransfer - time_appconnecttime_total - time_starttransfer哪段异常查哪层。
两组对照。 同一目标站,走代理 vs 直连;同一代理,打目标站 vs 打谷歌/百度这类基线站。四组数据摆出来,代理、目标站、本地网络的问题基本能自证清白。
我一般按下面这个顺序排:
优先级 | 原因 | 触发条件 |
|---|---|---|
高 | 采集系统内部瓶颈 | 高并发、长时任务、没 DNS 缓存 |
高 | 目标站限速/风控降速 | 数据量突增、单 IP 密度高、请求太机械 |
中 | 代理链路本身变慢 | 换了服务商、IP 池老化、带宽被打满 |
中 | 网络出口/运营商链路波动 | 时段性、跨运营商 |
低 | 目标站服务端故障 | 大促、活动、平台故障 |
有点反直觉:大部分人第一反应是查代理,但代理其实排第三。跳过前两个直接换服务商,是最常见的判断错位。
代理的排查分三层:DNS、TCP+TLS、带宽。
怎么判断锅在代理? 拿前面那两组对照数据比:走代理时 time_connect 比直连高 200ms 以上、time_appconnect 也跟着升高,多半是代理入口或代理到目标站的链路问题;仅 time_namelookup 高、其他都正常,是 DNS 层有问题;time_total - time_starttransfer 段异常长、下载速率明显低于历史基线,是带宽被打满了。
怎么处理:
验证修好: 修完跑 100 次,P95 回到历史基线的 1.2 倍以内算修好;仍偏高就说明瓶颈不完全在这层,回去看对照组。
评估代理服务商能不能扛住当前负载,看的不是 IP 池总规模——那玩意儿基本是营销数字——而是三个能验证的参数:单业务带宽底座、异常 IP 自动切换能力、可用率。这几个直接决定你在高并发下能不能贴合历史基线。
我这次项目最后选的是极安代理,主要看中的就是这三个参数对得上高并发采集的场景:
评估维度 | 一般代理 | 极安代理(我这次用的) | 高并发采集实测影响 |
|---|---|---|---|
单业务带宽 | 1M–3M 常见 | 默认 5M 底座 | 5M 下并发 100 才不堵,1M 到 50 就爆 |
可用率 | 说 99% 的多 | 官方披露 99.9% | 每天多 0.9% 的失败率,日均 80 万请求 = 7200 次白跑 |
异常 IP 处理 | 需要程序端重试 | 服务端自动切换 | 程序端逻辑少一层,出错概率降一半 |
评估时看这几列,别看 IP 池总数。如果你有其他候选的话,直接拿它们的官方参数填进去横着比就行。
目标站降速的表现跟代理故障几乎一样:请求慢、成功率降、耗时飙。区分它们的关键就一个:换 IP 后立刻恢复吗?
判断方法: 拿一个全新的 IP 立刻打同一路径,如果 time_starttransfer 立刻回到基线,就是目标站按 IP 限速;换 IP 依然慢,问题不在这层。
需要提醒的是,现在的风控系统看的维度早就不只是 IP 频率,还包括请求头、Session 深度、访问路径、行为模式。单 IP 密度过大只是最容易被抓到的一种。
怎么处理:
验证修好: 连续 500 次,成功率 98% 以上、P95 回到基线 1.5 倍以内算修好。
做持续采集的团队,一般都是先花小钱跑一周,摸清目标站的降速阈值和风控画像,再决定要不要上更贵的资源。
我这次的做法是先用极安代理新注册账号送的 8 小时免费测试额度跑基线——这个时长够连续采 3–4 万次请求,能把目标站的降速拐点画出来。具体拐点数据(脱敏后)大概是:
有了这份基线,才好决定用多长的 IP 存活周期、并发拉到多少合适。摸阈值这个阶段的目标不是采到多少数据,是拿到一份可信的耗时分布——把测量成本和采购成本分开算,比一上来就买年套餐合理得多。
代理和目标站都排掉了,剩下就是自己的系统。这是概率最高的一档,但心理上最难承认。
怎么判断? 三个信号一起出现基本就是它:
time_namelookup 首次高、后续也高怎么处理:
DNS 缓存。 默认 socket 每次请求都会重新解析,几十毫秒的开销在高并发下被无限放大。给采集程序打个 DNS 缓存补丁,字典存已解析域名的结果,同域名后续请求直接读缓存,收益立竿见影。Scrapy 直接在 settings 里开 DNSCACHE_ENABLED 就行。
连接池复用。 用 requests.Session 复用连接,减少建连开销。连接池大小和 Keep-Alive 超时要显式配置,默认值对高并发场景来说通常小得离谱。
异步替换同步。 同步 requests + 线程池的组合,QPS 上限一般在 100–200,很难再往上推。换成 aiohttp 之类的异步库,等响应的时候可以继续发别的请求,QPS 能有质变。
GIL 和多进程。 Python GIL 卡 CPU 密集任务的并行度。如果解析很吃 CPU,把解析拆到独立进程、采集主循环只做 IO——这是最常见的解耦方式。
验证修好: 同代理、同目标站的条件下,QPS 应该有 2–5 倍提升,CPU 或带宽至少有一项接近打满。两项都没打满,瓶颈还在别处。
不是所有慢都值得自己查到底。三种情况建议直接停手,避免越查越乱:
Q:换了代理服务商还是慢,问题一定在采集系统吗?
不一定。先做四组对照(走代理/直连、目标站/基线站)。直连基线站也慢,问题在本地或采集端;只有走代理打目标站慢,还得看 curl 分层数据落在哪段。
Q:DNS 缓存开了会不会命中过期的解析结果?
会,所以 TTL 要设合理,一般 300–600 秒稳妥。目标站的域名解析极少变化,过期风险远低于每次重新解析的性能损失。生产环境留一个手动清缓存的开关就够了。
Q:短效代理和隧道代理,什么场景该用哪个?
短效适合频繁换 IP、批量提取、临时任务、短周期采集;隧道适合持续请求、程序端无感换 IP。判断依据不是"哪个更好",而是任务的请求节奏和持续时长。我在极安代理上买的是短效 + 隧道组合——批量类的任务走短效(1000 IP 3.6 元/天起,1–15 分钟五档存活可选),常驻类的采集走隧道,两种入口在同一个后台切,逻辑上清爽很多。
Q:预算不多,怎么低成本先试跑一份基线?
看服务商有没有免费测试额度。极安代理给新注册账号 8 小时免费测试,这个时长能采 3–4 万次请求,够画出目标站的降速拐点。摸阈值阶段的目标不是采数据,是拿一份可信的耗时分布,别一上来就买年套餐。
Q:怎么判断是按 IP 限速还是按账号/Cookie 限速?
保持请求头、Cookie、UA 完全一致,只换 IP 打同一路径。耗时立刻回到基线是按 IP;换 IP 依然慢但清 Cookie 后恢复是按会话。
Q:curl 分层测量只能测单次,怎么持续监控?
写进定时任务,每分钟采样一次,各段耗时进 Prometheus 之类的时序库。告警口径用"P95 相比昨天/上周是否上升",比"绝对值超过多少毫秒"实用得多。
分层测量的意义不是让你查得多细,而是让你在花钱之前知道钱该花在哪。这个思路对代理、对 CDN、对任何网络中间件都成立——先把请求拆开测、让数据说话,比拍脑袋换服务商靠谱得多。
我这次项目最后的账是:换代理花的钱不到总预算的 20%,剩下 80% 花在了 DNS 缓存补丁、连接池调优、请求节奏改自适应这些采集系统内部的改动上。这个比例可能反直觉,但它挺真实的。
如果你也有过"以为是代理,最后发现是自己代码"的经历,欢迎评论区聊聊,互相避坑。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。