站点运营

站点运营:缓存与 CDN 自查,蜘蛛拿到的可能不是最新那版

缓存和 CDN 让页面访问更快,但也可能让蜘蛛读到旧版本甚至空壳页。这篇从整页缓存、错误状态缓存、登录态差异、TTL 设置几个角度整理了一份自查清单,并说明怎么用日志和不同 UA 请求,确认蜘蛛实际拿到的是什么内容。

站点运营

站点运营:缓存与 CDN 自查,蜘蛛拿到的可能不是最新那版

很多站点在排查抓取异常时,会先看服务器日志、robots.txt 和站点地图,却很少想到另一层:蜘蛛拿到的 HTML,可能根本不是数据库里最新的那一版,而是缓存层吐出来的旧副本。缓存本身没有错,问题是缓存和抓取之间的关系没被管理好。

缓存把页面变成了两份

开了一整页缓存之后,同一个 URL 至少有两份内容:一份是源站刚生成的,一份是缓存节点上躺着的。用户访问时命中缓存,页面秒开;而搜索引擎蜘蛛来的时候,如果也命中同一份缓存,它看到的就是缓存生成那一刻的内容。内容更新后,蜘蛛可能过一阵才拿到新版本。

这件事本身不一定出问题。真正麻烦的是两种情况:缓存里存的是错误页面,或者不同访问者拿到的内容差异过大。

几类常见的不一致

1. 缓存了错误状态

源站某次抖动返回 500,或者数据库连接失败返回一个空壳页,如果这类响应被 CDN 按正常页面缓存下来,接下来一段时间所有访问者和蜘蛛都会拿到这个错页。常见表现是:日志里同一个地址反复返回 200,但内容却是空的。

2. 带登录态的差异

有些主题或插件会根据 Cookie 判断登录状态,未登录时展示摘要,登录后展示全文。如果缓存没有正确区分,蜘蛛(通常不带 Cookie)可能拿到一份权限受限的版本,正文大面积缺失。

3. TTL 设得太长

把 HTML 的缓存时间设成几天甚至几周,适合更新不频繁的静态页,但对栏目首页、文章页就不合适。新发布的内容如果只在源站可见,蜘蛛抓到的还是旧版,发现和收录都会被拖慢。

4. 地域与设备分流被缓存串味

多语言站点按 IP 判断语言、移动端返回精简版 HTML,这类分流如果和缓存策略没配合好,可能让蜘蛛在同一个地址上反复拿到不同语言的页面,导致它对这个地址的主版本判断摇摆。

自查清单

  1. 用一个干净的、不带 Cookie 的请求访问核心页面,检查返回内容是否完整,正文、标题、内链是否都在。
  2. 换一个常见的搜索引擎蜘蛛 UA 再请求一次,对比两次返回的 HTML 是否一致。
  3. 故意请求一个不存在的地址,确认返回的是 404,而不是一个被缓存的 200 空页面。
  4. 检查 CDN 后台有没有开启错误响应缓存,如果有,确认 5xx 的缓存时间是否被压到很短的秒级。
  5. 核对 Cache-Control 里的 s-maxage 与实际内容更新频率是否匹配,栏目页和文章页可以给不同档位。
  6. 看服务器日志里蜘蛛抓到的页面大小分布,如果同一批地址响应体忽大忽小,值得查一查缓存分层。

响应头可以怎么设

HTML 文档一般不建议让边缘节点长时间缓存。比较稳妥的做法是给一个较短的 s-maxage,配合 stale-while-revalidate,让节点在回源更新的同时继续提供旧内容,避免用户等待。真正需要长缓存的,是图片、CSS、JS 这类带版本号或指纹的静态资源,它们改名后地址会变,不容易出错。

同时留意 Vary 头。如果站点按 User-Agent 或 Accept-Language 返回不同内容,Vary 要写清楚,否则缓存可能把 A 的版本发给 B。写错 Vary 也会让缓存命中率下降,回源压力反而变大。

怎么确认蜘蛛看到的是什么

最直接的办法是拿日志说话。挑几个重点地址,记录蜘蛛访问的时间点、返回状态码和响应体大小,再和自己的手动请求做对比。如果响应体大小长期稳定,但页面内容其实已经更新过,基本可以判断命中的是旧缓存。也可以临时给这类地址加上较短缓存或直接绕过缓存,观察抓取到的内容是否随之变化。

另外,站点地图里的 lastmod 如果和缓存里实际的版本对不上,也容易让蜘蛛产生误判。更新内容之后,顺带确认一下缓存有没有被主动刷新,比等着 TTL 自然过期更省事。

缓存的目标是让用户更快看到内容,而不是让蜘蛛一直看到旧内容。把缓存时间、回源策略和内容更新节奏对齐,抓取和展示才会各自正常。