很多蜘蛛池入口页并不是直接暴露源站,而是挂在 CDN 或反向代理后面。搜索引擎蜘蛛请求 URL 时,先到达边缘节点;如果命中缓存,它拿到的是缓存副本,而不是源站实时生成的那份 HTML。这一点如果被忽略,就会出现“我在源站明明改好了,蜘蛛看到的还是旧内容”的困惑。
蜘蛛访问 CDN 时发生了什么
CDN 的本质是在离用户和蜘蛛更近的节点上放一份副本。节点判断请求能不能用缓存回答,能就直接返回,不能就回源站取一次,再按规则决定是否留存。对蜘蛛来说,它并不关心背后是源站还是边缘节点,它只认这次 HTTP 响应里的状态码、响应头和正文。
命中缓存与回源
如果缓存未过期,边缘节点直接返回旧副本;如果缓存已过期或不存在,节点回源。回源这一步如果源站响应慢、超时或报错,有些 CDN 会返回自己生成的错误页,而不是把源站的真实状态透传给蜘蛛。蜘蛛看到的是一个 200 状态码,正文却是“服务暂时不可用”之类的提示,这种情况在入口页上尤其容易被误判为“页面正常”。
缓存键决定“同一个 URL”的含义
缓存键通常由域名、路径、查询参数、请求头等要素组合而成。如果缓存键把某些查询参数也算进去,那么带参数的 URL 和不带参数的 URL 会被当成两个不同对象,各自缓存一份。对蜘蛛池入口页来说,这可能导致同一批链接被拆成多个缓存变体,增加节点存储和回源次数,也让内容更新变得更难同步。
几类常见的缓存问题
- 缓存版本滞后:源站已经改了入口页的链接或文字,边缘节点还在返回旧副本。蜘蛛按固定频率来抓,拿到的仍是上一版内容。
- 缓存键包含无关参数:统计参数、来源标记等被算进缓存键,同一路径产生大量缓存变体,回源压力上升。
- 回源失败返回 200:源站 5xx 或超时,CDN 用自己的错误页替代,蜘蛛收到 200,正文却是空壳或提示语。
- 错误状态被缓存:404、503 被节点缓存一段时间,蜘蛛下次来仍然拿到错误页,即使源站已经恢复。
- Vary 头设置不当:按 User-Agent 区分缓存时,蜘蛛拿到的可能是为浏览器准备的版本,或者反过来。
缓存头怎么设比较稳妥
入口页不是静态资源,不建议设置过长的缓存时间。对于需要定期更换链接、调整模板的页面,可以把 Cache-Control 设为较短的 max-age,配合 stale-while-revalidate 之类的策略,让节点在后台更新,而不是把旧副本长期挂在那里。若页面内容对访问者身份不敏感,尽量不要用 Vary: User-Agent,否则蜘蛛和普通访客会各存一份,既浪费节点空间,也容易让两边看到不一致的版本。
另外,源站的错误状态不要被 CDN 改写成 200。回源异常时,宁可让蜘蛛看到真实的 5xx 或超时,也不要给它一个“看起来正常”的空页。错误页被缓存后,清理起来往往比重新回源更麻烦。
判断入口页是否被缓存拖累,不要只看源站日志。源站日志里可能只有 CDN 回源那几次请求,蜘蛛在边缘节点命中缓存时,源站完全不知情。
验证蜘蛛实际拿到什么
可以用几种方式交叉验证:一是直接请求入口页 URL,观察响应头里的缓存命中标记、Age、X-Cache 等字段;二是用与搜索引擎蜘蛛相近的 User-Agent 发起请求,对比返回正文是否一致;三是在源站和 CDN 分别打日志,看同一次抓取是否只到了边缘、有没有回源。若发现缓存版本和源站不一致,先确认缓存键和缓存头,再决定是刷新缓存还是调整规则。
使用建议
- 入口页上线前,先确认 CDN 缓存规则和缓存键设置,避免参数污染。
- 需要更新内容时,判断是改源站就够,还是必须同时刷新边缘缓存。
- 不要把入口页当成静态文件长期缓存,给蜘蛛留出看到新版本的机会。
- 回源异常时保留真实状态码,不要让 CDN 错误页伪装成 200。
- 定期抽查边缘节点返回的正文,而不是只信任源站自测结果。
CDN 和缓存层本身不是问题,问题在于入口页的内容更新节奏与缓存策略是否匹配。把缓存当作蜘蛛访问链路中的一环来看,很多“蜘蛛没反应”的疑问会更容易定位。