搜索抓取

304 与 If-Modified-Since:蜘蛛二次访问时省下的那一趟

蜘蛛第二次访问同一个 URL 时,常会先问一句“内容变了没有”。服务器回一个 304,就能省下一整页正文的传输。本文讲清条件请求的触发过程、Last-Modified 与 ETag 常见的误配,以及怎么在响应头和访问日志里把它检查出来。

搜索抓取

304 与 If-Modified-Since:蜘蛛二次访问时省下的那一趟

蜘蛛对一个 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 和完整正文。对自己来说是省了事,对蜘蛛来说带宽一点没省。

条件请求被当成异常流量

这类请求头字段不常见,个别防护规则会把它拦下。可以在日志里留意有没有被拦截的记录。

怎么检查,怎么调

  1. 在访问日志里统计栏目页、详情页的 304 占比,占比过低先看响应头是不是真的给出了校验值。
  2. 用 HEAD 请求连续访问两次同一个 URL,看第二次是否返回 304,以及两次的 ETag 是否一致。
  3. 确认 CDN 与源站的校验值一致,避免边缘节点自己重写。
  4. 把 304 响应压到最小,不附带正文,也不要顺手塞大段调试头。
  5. 让 Sitemap 里的 lastmod 与页面的 Last-Modified 大体一致,两个信号互相矛盾时,蜘蛛更容易按保守的一侧处理。
304 只说明“这次内容没变”,并不代表蜘蛛不会再来。它省的是传输成本,不是抓取次数;把 304 当成降低抓取频率的手段,方向就偏了。

整体上,条件请求属于投入很小、收益稳定的那一类改动。它不会让该抓的页面多抓一个,但能让蜘蛛在同样的时间窗口里把抓取额度用得更从容——页面多、更新少的站点,差别会随着时间慢慢显现。