给蜘蛛池的入口站套上 CDN,是很多人顺手就会做的事:省带宽、抗压,顺便遮一下源站 IP。但套完之后往往会发现,蜘蛛的抓取表现和预期不太一样——有时更顺,有时反而变差。原因大多不在 CDN 本身好不好,而在于蜘蛛拿到的到底是一份缓存副本,还是回源之后的实时内容。
蜘蛛请求也会命中缓存
CDN 节点不区分访客是谁,只要 URL、请求方法、请求头组合匹配缓存键,就直接把副本返回。主流搜索引擎的蜘蛛 UA 通常是公开的,节点不会因为它是蜘蛛就强制回源。也就是说:如果这个 URL 之前已经被别人或蜘蛛自己请求过,并且缓存还没过期,蜘蛛读到的就是那份副本,源站根本没收到这次请求。
这本身不是坏事。副本稳定、响应快,蜘蛛读取意愿一般不会差。问题出在副本已经不代表当前真实状态的时候。
几种常见的回源行为及其影响
- 强制回源:每次请求都打到源站。抓取压力回到源站,但内容一定是最新的,适合入口页需要频繁变更的场景。
- 长缓存且不刷新:蜘蛛长期读到旧版本。如果入口页的出链结构已经调整,蜘蛛看到的还是老链接,URL 发现效率会打折。
- 各节点独立缓存:不同节点缓存过期时间不一致,蜘蛛从不同出口 IP 访问,可能拿到内容有差异的几份副本。
缓存策略上比较稳的几条做法
- 入口页 HTML 设一个偏短的缓存时间,比如几分钟到几十分钟,让内容更新能较快体现,同时又能挡住瞬时压力。
- 静态资源如 CSS、JS、图片可以放心长缓存,它们不承载出链关系。
- 明确区分状态码:正常页缓存,301 可以缓存,但 5xx 和临时错误别缓存,避免蜘蛛反复读到错误页。
- 如果确实要按 UA 返回不同内容,务必在响应里声明 Vary,否则缓存会串味,把 A 版本发给 B 类访客。
缓存不是用来骗蜘蛛的,而是告诉它:这份内容在这个时间窗口内是可信的。窗口设得太长,你就是在让蜘蛛读历史。
容易被忽略的几个坑
- 节点回源失败时返回自定义错误页,但状态码写的是 200,蜘蛛会把错误页当正常内容处理。
- CDN 默认开了防盗链或访问频率限制,蜘蛛密集抓取时被拦,返回 403,日志里表现为蜘蛛来过但没读成。
- 源站做了 IP 白名单,只放行 CDN 回源段,结果蜘蛛直连源站时被拒——本来没事,改配置之后反而出事。
- 换 CDN 厂商或调整节点后没有清缓存,旧副本还留在节点上。
怎么验证蜘蛛读到的是哪一份
- 用蜘蛛 UA 手动请求一次入口页,看响应头里的缓存命中标识,例如 X-Cache、Age。
- 对比源站日志与 CDN 日志:源站请求数远小于 CDN 侧请求数,说明大部分是命中缓存。
- 改动入口页内容后,按缓存时间等待,再用蜘蛛 UA 复测,确认版本已经更新。
- 观察一段时间内不同出口 IP 的返回是否一致,不一致就回头查节点缓存策略。
把 CDN 当成入口站的一层缓冲是合理的,前提是你清楚蜘蛛在什么情况下拿到的不是源站刚生成的那份 HTML。花十分钟核对一次缓存头,往往比反复调整入口页结构更有效。