搜索抓取

搜索蜘蛛抓取:响应超时与首字节延迟造成的抓取放弃排查

蜘蛛抓取失败并不等于服务器宕机,更多时候是响应太慢。本文区分连接超时、读取超时与首字节延迟三类记录,梳理数据库、缓存、外部接口等常见慢点,给出分级处理、超时阈值与分位数监控的做法,让重要入口尽量留在被抓取的快路径上。

搜索抓取

搜索蜘蛛抓取:响应超时与首字节延迟造成的抓取放弃排查

很多人看到抓取日志里成片的超时记录,第一反应是服务器挂了。但登录机器一看,负载正常、CPU 空闲、磁盘也没满。这种情况多半不是可用性问题,而是速度问题:蜘蛛在等待响应的窗口内没有拿到足够的数据,就主动断开,转去抓别的 URL 了。

可用性和响应速度是两件事。前者决定蜘蛛能不能连上,后者决定它愿不愿意等。慢,在抓取层面几乎等价于不可用。

日志里的三类超时,含义并不相同

把超时笼统归成一类,排查会一直打转。按发生阶段拆开看,至少有三种:

  • 连接超时:TCP 握手阶段就没完成。常见于防火墙丢包、源站被限速、回源链路抖动。日志里通常表现为连接建立失败。
  • 读取超时:连上了,但等待响应体的时间过长。典型是后端接口阻塞、数据库慢查询、模板渲染卡住。
  • 首字节延迟(TTFB)偏长:请求发出到第一个字节返回之间耗时明显。它本身不一定触发超时,但会持续消耗蜘蛛的并发等待额度。

这三类的修复方向完全不同:连接超时找网络与限流,读取超时找后端逻辑,TTFB 偏长则要看缓存命中与动态渲染路径。混在一起看,容易得出“服务器不稳定”这种没有指向性的结论。

为什么慢会被直接放弃

蜘蛛的抓取是并发的,同时打开的连接数量有限。一个慢 URL 占住一个连接槽位,其他 URL 就得排队。当某个请求超过等待上限,蜘蛛不会一直守在那里,它会断开并把这个 URL 的失败计入本次记录。

后果是连锁的:慢页面被反复尝试、反复失败,占用的额度却挤掉了本可以顺利抓取的其他 URL。久而久之,你会看到抓取总量下降,但抓取失败的记录集中在少数同一批 URL 上——这通常不是站点整体坏了,而是少数入口拖累了整体节奏。

常见慢点排查清单

  • 列表页或详情页存在未加索引的查询,数据量涨上来后单次响应从毫秒级退化到秒级。
  • 页面渲染依赖外部接口,且是串行调用,任一接口抖动都会拉长整体响应。
  • 缓存命中率低,或缓存键设计过细导致几乎不命中,每次请求都走完整后端。
  • 响应体本身过大,正文前置不足,蜘蛛读到后面才拿到关键内容。
  • 静态资源与 HTML 走同一套动态逻辑,图片、附件请求也在消耗应用进程。
  • 回源带宽或出口被大流量任务占满,白天表现尤其明显。

排查时建议按 URL 分组看响应时长分布,而不是只看站点平均值。平均值会被大量快页面稀释,掩盖掉那批一直很慢的入口。

处理思路:分级,而不是全面提速

  1. 分级:把首页、栏目页、重要详情页列为高优先路径,确保它们走缓存或静态化;长尾页、历史归档可以接受稍慢。
  2. 砍掉串行:能并行取的数据并行取,能给默认值先渲染的就先渲染,不阻塞首字节。
  3. 设内部超时:给后端调用和数据库查询设置比蜘蛛等待上限更短的超时,让站点自己先降级返回,而不是把连接挂到蜘蛛放弃。
  4. 控制并发:对耗时较长的接口单独限流,避免慢任务把应用进程池占满,连带影响快路径。
  5. 监控分位数:关注 P90、P95 响应时间,而不是平均响应时间。抓取放弃往往发生在尾部,而非中部。

和 429、503 不是一回事

429 和 503 是站点主动表达的“请慢一点”或“暂时不可用”,蜘蛛通常会据此调整抓取速率并稍后重试。超时则是被动断线,蜘蛛拿不到明确信号,只能按失败处理,重试节奏也更难预测。

因此不要用超时来充当限流手段。想降速就明确返回 429 或 503,并配合合理的 Retry-After;靠拖时间逼退蜘蛛,只会让日志里堆满无法解释的失败。

如果同一批 URL 连续多天以超时形式失败,先确认它们是不是共用了同一个慢接口或同一条数据查询,而不是急着换服务器。

值得长期观察的几个指标

  • 抓取请求中成功响应的 P95 耗时,以及它随时间的趋势。
  • 超时失败占全部抓取请求的比例,按 URL 路径前缀分组。
  • 缓存命中率与静态化覆盖率的变化。
  • 同一 URL 在多次抓取中的耗时波动幅度,波动大往往意味着依赖了不稳定外部资源。
  • 抓取总量与失败总量之间的比值,用来判断是入口问题还是整体节奏问题。

抓取稳定性最终落在两件事上:让快路径一直快,让慢路径不要拖住别人。做到这两点,超时类失败通常会明显收敛,剩下的问题也更容易定位。