站点运营

站点运营:CDN 与缓存策略自查,别让过期页面继续被发给蜘蛛

CDN、反向代理和浏览器缓存能减轻源站压力,但也可能把旧版页面持续发给爬虫。本文从缓存响应头、HTML 与静态资源的差异化策略、Vary 维度区分、刷新与预热、状态码缓存等角度,给出一份可逐项核对的缓存自查清单。

站点运营

站点运营:CDN 与缓存策略自查,别让过期页面继续被发给蜘蛛

缓存是加速器,也可能是信息延迟器

CDN、反向代理、对象缓存的存在,本意是让用户更快打开页面、让源站少扛压力。但只要缓存策略设置得过于粗放,同样的机制就会带来另一个结果:内容已经改了,蜘蛛拿到的还是几天前的版本。抓取频率有限的站点,如果每次访问都落在过期缓存上,更新就等于没有发生。

这类问题通常不会在浏览器里被发现——你自己登录后台看到的往往是刷新后的版本,而匿名访客和爬虫看到的是缓存副本。所以它值得单独列入自查清单。

先弄清楚页面有几层缓存

  • 浏览器缓存:由返回的 Cache-Control、Expires 响应头控制。
  • CDN 边缘节点缓存:按 URL、查询串、请求头等规则生成缓存键。
  • 反向代理缓存:常见于源站前一层,容易和 CDN 叠加。
  • 应用层缓存:整页静态化、对象缓存、片段缓存,常被忽略。

自查的第一步不是改配置,而是搞清楚一个 URL 从请求到返回,中间到底经过哪几层。层数不清楚,后面所有调整都是猜。

核心原则:HTML 短缓存,静态资源长缓存

最简单的区分方式是看资源类型:

  • HTML 文档:缓存时间不宜过长,通常几分钟到几小时,并保留 ETag 或 Last-Modified 便于协商缓存。
  • 带指纹的静态资源:CSS、JS、图片可以设置很长的缓存时间,因为文件名带版本号,更新时 URL 会变。
  • 不带指纹的静态资源:要么加上哈希,要么缩短缓存时间,否则改一次样式要等很久才生效。
  • 接口与动态内容:明确是否需要缓存,不要用默认值蒙混过去。

如果整站 HTML 都设置了长期强缓存,就等于告诉抓取工具“这个地址的内容很久不会变”,之后你再怎么更新,也缺少重新拉取的动机。

容易被忽略的几处细节

Vary 与多端、多语言版本

移动端和桌面端返回不同 HTML,或者按语言目录返回不同内容时,要确认缓存键里包含了区分维度(如 Vary: User-Agent,或按目录、按地区拆分缓存)。否则可能出现移动端用户拿到桌面版页面、A 语言版本被 B 语言覆盖的情况。

更新后的刷新与预热

内容发布、模板调整、栏目改版之后,记得主动清理相关 URL 的缓存。批量更新可以按目录或标签刷新,重要页面刷新后顺手访问一次做预热,避免第一个访客——或者第一次抓取——承担回源慢的代价。

出错时不要拿旧内容顶替

源站异常时,部分 CDN 支持返回陈旧副本(stale-if-error)。对用户体验来说这是好事,但如果源站持续报错而你并不知情,蜘蛛会一直拿到旧页面,误以为站点一切正常。建议对回源错误率单独设置告警。

状态码也会被缓存

301、302、404、410 这些响应同样可能进入缓存。做过跳转调整或页面下线后,要确认旧地址的响应没有停留在缓存里,否则抓取会继续沿着已经废弃的路径走。

可执行的核对步骤

  1. 用带匿名身份的请求(如 curl -I)查看目标 URL 的响应头,记录 Cache-Control、Age、ETag、Last-Modified、Vary。
  2. 对比源站直连和经过 CDN 的响应头,确认差异是否符合预期。
  3. 从不同地区或不同网络多次请求同一 URL,观察返回内容和 Age 的变化,判断是否命中同一节点。
  4. 抽查日志中的缓存命中率与回源比例,命中率异常高时反而要警惕。
  5. 发布一次小改动,记录它在各节点生效所需的时间,形成心理预期。
缓存策略没有统一答案,关键是把“什么该缓存、缓存多久、什么时候失效”写清楚,并且能在更新后验证生效范围。

别用缓存掩盖源站问题

还有一种反向的误区:把缓存时间拉到很长,用命中率来掩盖源站响应慢、数据库查询重的事实。这会让排障更困难,也会让内容更新变得更不可控。缓存应当是对性能的补充,而不是对问题的遮蔽。

把缓存层当作站点结构的一部分来维护,定期核对策略与生效情况,蜘蛛和用户才能稳定地拿到当前版本的内容。