蜘蛛對一個 URL 的第二次、第三次訪問,往往不是把整頁重新下载一遍。它會先發一個带條件的請求,服務器判断内容没變,就回一個很短的 304 响應。單次省下的字节不多,但乘上全站頁面數和抓取频次,省下的是實打實的带宽和响應時間。
條件請求是怎么發生的
第一次抓取时,服務器在响應头里给出 Last-Modified 或 ETag。下一次蜘蛛再来,就會带上 If-Modified-Since 或 If-None-Match,把上次拿到的值原样送回来。服務器比對之後:
- 内容没變:返回 304,不带正文,头里可以繼續带上目前的校驗值。
- 内容有變:返回 200 和完整頁面,同时给出新的校驗值。
- 校驗值對不上或缺失:只能当作一次全新請求處理。
鏈路上還有 CDN、反向代理、WAF 几层,任何一层把條件請求头丢掉,304 就無從谈起。
几種常见的誤配
Last-Modified 每次都刷新
把模板渲染時間、缓存刷新時間、目前時間寫進 Last-Modified,蜘蛛每次拿到的都是新值,條件請求永遠成立,等于没做。
ETag 不稳定
用 inode、進程号、部署時間、随机數拼出来的 ETag,每次發布、每次重啟就全站換一遍。更稳妥的做法是让 ETag 只跟内容本身相關,比如正文的哈希。
判断了却仍返回 200
有些應用發現内容未變後,只是跳過了資料库查询,仍然吐出 200 和完整正文。對自己来说是省了事,對蜘蛛来说带宽一点没省。
條件請求被当成異常流量
這類請求头字段不常见,個別防護規則會把它拦下。可以在日誌里留意有没有被拦截的记錄。
怎么检查,怎么調
- 在訪問日誌里統計栏目頁、詳情頁的 304 占比,占比過低先看响應头是不是真的给出了校驗值。
- 用 HEAD 請求连續訪問两次同一個 URL,看第二次是否返回 304,以及两次的 ETag 是否一致。
- 確認 CDN 與源站的校驗值一致,避免邊缘节点自己重寫。
- 把 304 响應压到最小,不附带正文,也不要顺手塞大段調试头。
- 让 Sitemap 里的 lastmod 與頁面的 Last-Modified 大体一致,两個信号互相矛盾时,蜘蛛更容易按保守的一侧處理。
304 只說明“這次内容没變”,並不代表蜘蛛不會再来。它省的是传輸成本,不是抓取次數;把 304 当成降低抓取频率的手段,方向就偏了。
整体上,條件請求属于投入很小、收益稳定的那一類改動。它不會让该抓的頁面多抓一個,但能让蜘蛛在同样的時間窗口里把抓取額度用得更從容——頁面多、更新少的站点,差別會随着時間慢慢顯現。