很多蜘蛛池入口頁的疑难問题,最後會落到缓存上。你本地打開看到的是新版本,蜘蛛抓到的可能是几小时前甚至几天前的舊版本。這不是蜘蛛记性差,而是請求在到達源站之前,就被某一层缓存截住了。
一、請求到源站前會经過哪几层缓存
一次蜘蛛抓取,通常要穿過下面几层,任何一层给出缓存副本,源站就不會被訪問。
- 浏览器缓存:只影响真實用戶,蜘蛛一般不复用本地缓存,排查时可以忽略。
- CDN 邊缘节点:影响最大的一层。不同节点的缓存狀態可能不一样,同一 URL 在不同地区抓到的版本未必相同。
- 反向代理與網關:Nginx、Varnish 之類的缓存层,規則不清时容易長期返回舊内容。
- 對象存储與静態托管:如果入口頁是静態文件,還要看它的缓存策略和刷新机制。
二、和蜘蛛拿到的版本相關的几個响應头
蜘蛛不执行复杂的缓存逻辑,但它拿到的是哪一份副本,基本由下面這些头决定。
- Cache-Control:max-age 决定副本能存活多久。给入口頁设過長的 max-age,更新後蜘蛛還會拿到舊版。
- ETag / Last-Modified:源站用它們判断内容有没有變。如果這两個值在更新後没變,缓存层會認為内容没動。
- Vary:声明按哪些請求头区分缓存。比如按 User-Agent 分版本,一旦寫错,蜘蛛可能拿到给移動端的那份。
- Age / X-Cache:排查时最直观的两個头,Age 顯示副本存活了多久,X-Cache 會告诉你這次是命中還是回源。
三、几個容易被缓存坑到的场景
1. 更新内容後蜘蛛仍抓舊版
最常见的情况。改完入口頁只刷新了自己的浏览器,CDN 节点並没有刷新。建议更新後主動做一次缓存刷新,等回源生效後再观察日誌。
2. 带參數的 URL 被当成獨立副本
入口頁 URL 上带 utm、from、ref 之類參數时,有些 CDN 會把它們当成不同资源分別缓存。结果同一篇内容在缓存里存了好几份,更新时只刷了一份。
3. 回源失敗返回舊内容
部分缓存配置在源站超时或 5xx 时會返回過期副本。蜘蛛看到 200 和正常内容,但源站其實已经挂了。這種情况日誌里不容易發現,需要看回源监控。
4. 按 UA 分版本導致串味
為不同蜘蛛准备不同版本时,如果 Vary 没寫對,CDN 會把 A 蜘蛛的副本發给 B 蜘蛛。入口頁内容本身没坏,但分發错了。
四、實操建议
- 入口頁的缓存時間不要设太長,尤其是内容還在調整的阶段,几十分钟到几小时比几天更稳妥。
- 每次更新後主動刷新缓存,並在刷新後用一個不常见的 UA 請求一次,確認返回的是新版。
- 用 curl -I 检查响應头,重点看 Cache-Control、Age、X-Cache、ETag。這一步比翻日誌快。
- 如果入口頁是静態文件,尽量让文件名或路径带版本标识,避免和舊缓存冲突。
- 给不同蜘蛛分版本时,先確認缓存层是否支持按 UA 区分,再看 Vary 寫得對不對。
- 记錄一次完整的抓取鏈路:蜘蛛請求到的节点、返回的 Age、是否回源。出問题时比盲猜有效。
缓存不改變内容本身,只改變蜘蛛什么时候看到哪一版。把這一层理清楚,很多關于蜘蛛不抓新内容的疑問會有答案。
缓存层的價值是减少源站压力,對蜘蛛池入口頁来说,它同时是一层看不见的變量。不必把它当成敌人,但要知道它什么时候會挡住你想让蜘蛛看到的東西。定期检查响應头,比事後從日誌里倒推省力得多。