在蜘蛛池里,CDN 经常被当成單纯的加速器来用,但它真正的作用更接近于把入口頁的訪問請求挡在离蜘蛛最近的一层。配得好,回源压力小、响應稳定;配得不好,蜘蛛看到的可能是缓存里的舊副本,甚至拿到 5xx。這篇文章只聊缓存與 CDN 相關的取舍。
先確認 CDN 适不适合你的入口頁
蜘蛛池入口頁大多结构简單、更新不频繁,用 CDN 承载本身是合理的。但 CDN 會改變蜘蛛實际拿到的東西——它拿到的是邊缘节点返回的副本,而不是源站實时生成的頁面。所以在調缓存之前先問自己一句:入口頁的内容多久變一次。長期不動的模板頁,缓存時間長一点没坏處;需要跟着目标頁轮換的頁面,缓存時間设長了就會出現蜘蛛抓到的還是上一批連結的情况。
先把角色分開看
CDN 负责的是最近的那一次請求,源站负责的是第一次和最真實的那一次。蜘蛛的第一次訪問通常不會命中缓存,命中之後才會走邊缘节点。所以調優时不要只盯着面板上的命中率,也要看源站在回源那一刻的表現。
缓存头具体怎么设
决定邊缘节点是否缓存、缓存多久的,主要是响應头里的几個字段。它們對蜘蛛和普通訪客一视同仁,蜘蛛不會因為 UA 不同就绕開缓存。
Cache-Control
- max-age:邊缘节点和浏览器都會讀。入口頁内容稳定时可以给到几小时到一天;需要跟着轮換的頁面建议压到几分钟,或者干脆让节点每次回源校驗。
- s-maxage:只作用于共享缓存,也就是 CDN。想單獨控制 CDN 的缓存时長就寫這個,比 max-age 更精准。
- no-store:完全不留副本。入口頁一般用不到,除非頁面内容是按請求實时拼接的。
- private:只允许浏览器缓存,CDN 不存。如果發現 CDN 缓存了不该缓存的頁面,检查是不是漏了這個。
ETag 與 Last-Modified
這两個是校驗用的。节点缓存過期後會带 If-None-Match、If-Modified-Since 回源,源站返回 304 就不用重传正文。對入口頁這種体积小但數量多的頁面,304 能省下不少回源带宽。要注意源站生成 ETag 的規則保持一致,否則每次回源都變成 200,缓存等于白设。
回源與响應表現
CDN 不命中时會回源,回源那一刻的速度由源站决定。源站本身 TTFB 就高的话,CDN 只能改善命中之後的表現,改善不了第一次抓取。蜘蛛第一次訪問通常都是不命中的,所以源站该做的精简還是得做。
另一個容易忽略的点是回源超时。源站偶尔慢一下,节点等不到响應就會返回 5xx 或 504,蜘蛛记到的就是一次失敗。把回源超时设得合理一些,配合源站自身的重试,往往比反复調缓存時間更有用。
常见的几個坑
- 缓存了带參數的 URL:入口頁如果带查询參數,而缓存键又包含全部參數,同一條内容會被拆成很多份缓存,命中率很低。可以考虑在 CDN 侧忽略掉没有實际意义的參數。
- 缓存了错誤頁:源站返回 404 或 500 时,如果 CDN 也把這些狀態碼按普通响應缓存下来,蜘蛛在缓存有效期内會一直看到错誤頁。
- 节点間内容不一致:不同地区节点缓存時間不同步,蜘蛛從不同出口訪問可能拿到新舊不一的内容。對入口頁来说通常不算大問题,但如果頁面里的連結需要统一,就得留意。
- 日誌被 CDN 吃掉:源站訪問日誌只记錄回源請求,蜘蛛的訪問记錄在 CDN 侧。要分析抓取情况得把 CDN 日誌拉下来,不然容易誤判成蜘蛛没来。
調整时的顺序
- 先確認入口頁的更新节奏,據此定缓存时長。
- 再看回源是否稳定,重点關注 5xx 和超时的比例。
- 然後看命中率。命中率低不一定代表配置错了,也可能只是頁面太多、訪問太散。
- 最後才是压缩、HTTP/2 這類传輸层優化,優先級放在後面。
CDN 和缓存只能改變頁面被取走的效率,改變不了頁面本身有没有價值。入口頁的内容和連結關系没理清,缓存調得再细,也只是让一批普通頁面被更快地取走。
總的来说,入口頁的 CDN 配置不需要多复杂:把缓存时長和更新节奏對上,把回源的错誤率压住,把日誌留住能看,基本就够用了。剩下的精力,建议放回入口頁本身的结构和連結组织上。