缓存是加速器,也可能是信息延迟器
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 這些响應同样可能進入缓存。做過跳轉調整或頁面下线後,要確認舊地址的响應没有停留在缓存里,否則抓取會繼續沿着已经废弃的路径走。
可执行的核對步骤
- 用带匿名身份的請求(如 curl -I)查看目标 URL 的响應头,记錄 Cache-Control、Age、ETag、Last-Modified、Vary。
- 對比源站直连和经過 CDN 的响應头,確認差异是否符合预期。
- 從不同地区或不同網絡多次請求同一 URL,观察返回内容和 Age 的變化,判断是否命中同一节点。
- 抽查日誌中的缓存命中率與回源比例,命中率異常高时反而要警惕。
- 發布一次小改動,记錄它在各节点生效所需的時間,形成心理预期。
缓存策略没有统一答案,關键是把“什么该缓存、缓存多久、什么时候失效”寫清楚,並且能在更新後驗證生效范围。
別用缓存掩盖源站問题
還有一種反向的誤区:把缓存時間拉到很長,用命中率来掩盖源站响應慢、資料库查询重的事實。這會让排障更困难,也會让内容更新變得更不可控。缓存應当是對性能的补充,而不是對問题的遮蔽。
把缓存层当作站点结构的一部分来维護,定期核對策略與生效情况,蜘蛛和用戶才能稳定地拿到目前版本的内容。