搜尋抓取

CDN 缓存與邊缘节点:蜘蛛在不同位置看到的可能不是一個版本

同一個 URL,在不同邊缘节点、不同缓存策略下返回的内容未必相同。蜘蛛命中冷缓存、回源超时或按 UA 分缓存时,拿到的連結集合也會變。本文梳理缓存键、Vary、回源失敗與多节点不一致带来的抓取差异,並给出几條可落地的核對方法。

搜尋抓取

CDN 缓存與邊缘节点:蜘蛛在不同位置看到的可能不是一個版本

很多站点上线 CDN 之後,會預設一件事:同一個 URL,不管谁来訪問,看到的都是同一份頁面。實际不是。蜘蛛從不同出口、不同地区發起請求,落到不同邊缘节点,缓存命中情况、回源时机、源站当时的健康狀態都可能不一样。结果就是,同一個 URL 在蜘蛛那邊可能出現過好几個版本,而你自己訪問时看到的一直是正常的那一個。

缓存键决定蜘蛛拿到哪一份

CDN 判断要不要用缓存,靠的是缓存键(cache key)。預設通常只包含 host、path 和 query,但很多配置會加入更多维度:设备類型、語言、Cookie、請求头。這些维度一旦和蜘蛛的請求头對不上,就會出現两種情况——要么蜘蛛每次都绕過缓存回源,要么蜘蛛拿到了一份给普通浏览器准备的缓存副本。

  • 按 UA 分缓存:移動蜘蛛和桌面蜘蛛命中不同副本,頁面里的連結可能不一样。
  • 按 Cookie 分缓存:蜘蛛不带 Cookie,容易命中未登入版本,可能缺少入口類連結。
  • 按地域分缓存:不同节点回源到不同源站或机房,内容發布時間有先後。

Vary 响應头會放大這個問题。一旦 Vary 里寫了 User-Agent 或 Cookie,缓存會被切得非常碎,命中率下降,回源請求明顯增加。對蜘蛛来说,抓取时延變大,同一批 URL 的抓取進度會被拖慢。

缓存没命中时,邊缘回源會遇到什么

蜘蛛訪問的往往是冷门 URL,缓存命中率比真實用戶低得多,基本每次都要触發回源。這时候源站的真實狀態才會暴露出来:

  1. 源站慢:邊缘等待超时,可能直接返回 5xx 或舊副本,蜘蛛收到的是失敗或不完整頁面。
  2. 源站限流:蜘蛛的並發請求被挡掉一部分,返回 429 或 503。
  3. 健康检查誤判:节点被摘除,部分請求落到兜底頁或错誤頁。

這些情况在浏览器里不一定看得出来,因為你訪問的大多是热頁面,缓存里有現成副本。要看清楚,得對比源站日誌和 CDN 日誌:CDN 日誌里的狀態碼分布,往往比源站日誌更能反映蜘蛛實际收到了什么。

邊缘节点之間很难完全一致

多节点部署时,缓存過期時間、预热策略、發布顺序都可能不同。一次内容更新之後,有的节点已经回源拿到新頁面,有的還在返回舊副本,中間可能持續几分钟到几十分钟。蜘蛛在這段時間里抓取,就會同时看到新舊两個版本,連結集合也可能不一样。

判断标准不是“我這邊打開正常”,而是不同节点、不同 UA、不带 Cookie 时返回的内容是否一致。

動手排查的几條路子

  • 用蜘蛛 UA 和不带 Cookie 的請求,對同一 URL 多次請求,比較响應内容與响應头,重点看 Age、X-Cache 這類字段。
  • 把請求打到不同地区节点,對比頁面里的連結數量和主要结构。
  • 核對 CDN 日誌與源站日誌:同一 URL 的請求量、狀態碼、响應時間是否對得上。
  • 對需要抓取的頁面明确缓存策略:静態頁给較長的 max-age,列表頁和詳情頁避免按 UA 切缓存。
  • 排除机器人识別規則:確認蜘蛛 UA 不會被誤判為異常流量而返回驗證頁。

配置上可以稳住几件事

第一,尽量让蜘蛛走和普通用戶一样的缓存逻辑,少按 UA、Cookie 分叉。第二,源站對蜘蛛常用的抓取路径保持稳定响應,不要動辄 5xx。第三,内容發布後主動预热關键节点,减少新舊版本並存的時間。第四,把 CDN 的兜底頁设成明确的狀態碼,不要用 200 返回一個加载中的空壳,那會让蜘蛛把空頁面当成正常内容记下来。

這些調整不會直接带来收錄,但能减少“蜘蛛看到的和你看到的不一样”這類無谓损耗。抓取本身是件需要确定性的工作,變量越少,越容易判断問题出在哪一步。