用户登录

技术文章

外部链接将在新标签页打开。

HTTP 缓存与 CDN 加速实践:把可缓存性写成响应头里的策略

一句话回答

HTTP 缓存与 CDN 加速的关键不在开启 CDN,而在于给每类资源写清可缓存性、复用条件与失效方式。本文对照 Cache-Control 主要指令、浏览器与共享缓存的差异、按资源分层的响应头组合、常见失效场景与上线顺序,并说明 st 系列扩展与厂商默认行为需另行核实。

想让 CDN 真正提速,先要回答一个更基础的问题:这份响应允许谁缓存、缓存多久、什么时候必须回来问源站。把答案写成明确的响应头,浏览器和 CDN 才会按同一套规则复用内容;没写清楚时,CDN 往往只能按默认规则处理或频繁回源,加速效果和正确性都会打折。

先区分两种缓存#

浏览器缓存是“私有缓存”,只服务一个用户;CDN 属于“共享缓存”,一份副本要发给很多用户。HTTP 缓存规范里的指令正是按这条界线设计的,误用的代价通常不是慢,而是把 A 用户的内容发给 B 用户。

指令含义主要影响
max-age=N响应生成后 N 秒内可复用私有与共享缓存都适用
s-maxage=N只针对共享缓存,并覆盖 max-ageCDN 的过期时间
no-cache可以存,但每次复用前必须验证不等于“不缓存”
no-store不存储用于敏感响应
private只允许私有缓存存储CDN 不保存
must-revalidate过期后必须验证,不得用过期副本牺牲可用性换一致性

最常见的误解是把 no-cache 当成“别缓存”。它的实际含义是“先验证再使用”,配合 ETag 时,命中验证会返回 304,省下的是响应体而不是往返。真正不想留痕的响应才用 no-store。

验证与缓存键:命中率的两根杠杆#

验证靠 ETag/If-None-Match,或更粗粒度的 Last-Modified/If-Modified-Since。CDN 命中时通常会带上 Age 头,表示这份副本已经在缓存里放了多久,可用于判断是边缘命中还是回源。

缓存键决定“什么算同一个资源”,Vary 是它的显式扩展。给 HTML 加 Vary: User-Agent 是常见的反面案例:UA 组合极多,副本被打散,命中率下降。按 HTTP 缓存规范,携带 Authorization 的请求,其响应默认不得被共享缓存复用,除非响应显式声明 public、s-maxage 或 must-revalidate。这条规则经常被忽略,也是鉴权接口串数据的来源之一。

按资源分层写策略#

不要给整站设同一个 max-age。更稳妥的做法是按“URL 是否会随内容变化”分层:

  • 带内容指纹的静态资源(如 app.3f2a1b.js):Cache-Control: public, max-age=31536000, immutable。内容变了 URL 也变,长缓存没有失效风险。
  • HTML 入口:Cache-Control: no-cache 加 ETag。每次都验证,未变更时回 304,保证用户拿到的是新资源引用。
  • 可公开的 JSON 接口:用 s-maxage 让 CDN 吸收突发流量,秒数由业务能接受的数据陈旧窗口决定,而不是照抄别人的配置。
  • 个性化或鉴权接口:private,必要时 no-store,并检查响应里有没有被一起缓存的 Set-Cookie。

一个响应头分层的示例#

下面的配置仅用于说明分层思路,未执行,也未在具体 CDN 或 Nginx 版本上验证:

# 示例,未执行;add_header 的继承规则需按实际配置核对
location ~* \.(js|css|woff2)$ {
    add_header Cache-Control "public, max-age=31536000, immutable";
}
location = /index.html {
    add_header Cache-Control "no-cache";
    etag on;
}

观察是否生效可以看响应头,同样属于未执行的示例命令:curl -I https://example.com/index.html,重点看 Cache-Control、ETag、Age 三项。

上线顺序与失效路径#

  1. 先发布新指纹的静态资源,确认可访问;
  2. 再更新 HTML,让它引用新文件名;
  3. 需要主动失效时,只清入口 HTML,而不是清整站长缓存资源。

反过来做,用户会在短时间内拿到“新 HTML + 旧资源”或“旧 HTML + 新资源”的组合。另外,stale-while-revalidate 与 stale-if-error 属于扩展指令,源站过期后是否仍能返回旧副本,取决于缓存实现,不能当作通用保证。

还需要核实什么#

本文依据的是 HTTP 缓存语义中的通用定义,未附厂商文档,也没有联网核验。具体 CDN 的默认缓存规则、清除粒度与耗时、是否支持上述扩展指令、以及 immutable 在边缘节点的处理方式,都随厂商与套餐不同,待核实,上线前应逐条对照所用 CDN 的文档与自己的响应头实际输出。

作者:沐小悠

本文约 5 分钟读完 · 关键词:HTTP 缓存、Cache-Control、CDN 加速、s-maxage、ETag

更多文章 GET 示例接口

「」标签下的其他文章