第3章 s-maxage 指令:共享缓存专用、与 max-age 区别、CDN 场景

3.1 概念解释

s-maxage 是 Cache-Control 响应指令之一,全称为 shared maximum age,专门用于约束共享缓存(如 CDN 边缘节点、反向代理、API 网关)的存储时长。当源服务器在响应头中同时携带 max-age 与 s-maxage 时,共享缓存必须优先采用 s-maxage,而私有缓存(浏览器)则忽略 s-maxage,回退使用 max-age。

核心语义:s-maxage 只为共享缓存“量身定制”,让 CDN 等中间节点可以遵循与浏览器不同的缓存策略,实现“浏览器缓存久一点、CDN 缓存短一点”的精细控制。

下面是一个典型的响应头示例,同时设置了两个指令:

Cache-Control: max-age=3600, s-maxage=600

在这个例子中:

  • CDN 节点读取 s-maxage=600,缓存 600 秒(10 分钟)后视为过期。
  • 浏览器忽略 s-maxage,仅认 max-age=3600,缓存 3600 秒(1 小时)。

这一机制在 CDN 加速场景中极为常用:源站希望浏览器长期缓存以减少重复请求,同时要求 CDN 频繁回源验证内容是否更新,从而保证用户始终能快速获取最新版本。

3.2 与 max-age 的核心区别

对比维度 max-age s-maxage
适用范围 所有缓存(私有 + 共享) 仅共享缓存(CDN、反向代理等)
优先级 共享缓存中低于 s-maxage 共享缓存中高于 max-age
私有缓存行为 完全生效 被忽略,回退到 max-age
典型值设定 较长(如 3600、86400) 较短(如 60、600)
主要用途 控制浏览器本地缓存 控制 CDN / 中间代理缓存
记忆口诀:“s 代表 shared,专管中间站;max-age 是通用档,浏览器自己看。”

3.3 原理图解

下图展示了一次用户请求经过浏览器缓存、CDN 节点最终到达源服务器的完整链路,以及 max-age 和 s-maxage 在不同缓存层级中的生效位置:

s-maxage 与 max-age 在缓存链路中的分工 客户端侧 缓存层 源站侧 用户浏览器 发起请求 浏览器私有缓存 使用 max-age 计算新鲜度 CDN 共享缓存 优先使用 s-maxage 源服务器 设置缓存指令 响应携带指令 应用 s-maxage=600 应用 max-age=3600 关键概念 • s-maxage 仅在共享缓存(CDN、反向代理)中生效,优先级高于 max-age • max-age 适用于所有缓存,包括私有缓存和共享缓存(当 s-maxage 未设置时) • 同时设置两者可实现“浏览器缓存长、CDN 缓存短”的差异化控制

3.4 类比理解

想象一下公司的公共冰箱和你的个人办公桌抽屉:

  • 个人抽屉(私有缓存)——你放了一份便当,贴上标签“保质期 3 天”(max-age)。只有你自己会取用,保质期完全由你决定。
  • 公共冰箱(共享缓存)——所有同事都能打开,行政部统一管理,在冰箱门上贴了告示:“所有公共食材保质期 1 天”(s-maxage)。即使便当盒上写的是 3 天,在冰箱里也按 1 天执行。

这个例子清晰地说明了:同一个物品在不同“缓存层”可以遵循不同的过期规则。s-maxage 就是行政部给公共冰箱定下的统一规则,优先级高于个人标注。

3.5 常见误区

注意:以下误区在实际项目中经常导致缓存策略失效,需要特别警惕。
  1. 误区一:s-maxage 可以完全替代 max-age
    只设置 s-maxage 而不设置 max-age,会导致浏览器无法获得明确的缓存时长,可能回退到启发式缓存。正确的做法是两者同时设置,各司其职。
  2. 误区二:s-maxage 在浏览器中也生效
    部分开发者以为 s-maxage 是一个“更强的 max-age”,在所有地方都生效。实际上浏览器会完全忽略 s-maxage,只认 max-age 或 Expires。
  3. 误区三:s-maxage 优先级永远高于 max-age
    优先级的高低取决于缓存类型。在共享缓存中 s-maxage 确实覆盖 max-age,但在私有缓存中 s-maxage 根本不参与比较。
  4. 误区四:s-maxage=0 会禁止所有缓存
    s-maxage=0 仅强制共享缓存立即过期,浏览器仍然可以按照 max-age 缓存。要彻底禁止缓存,应使用 no-store。

3.6 练习题

题目:某网站使用 CDN 加速,源服务器返回以下响应头:

Cache-Control: max-age=7200, s-maxage=600

请问在 CDN 节点和浏览器中,内容的缓存时长分别是多少?

  • A. CDN 缓存 7200 秒,浏览器缓存 600 秒
  • B. CDN 缓存 600 秒,浏览器缓存 7200 秒
  • C. CDN 缓存 7200 秒,浏览器缓存 7200 秒
  • D. CDN 缓存 600 秒,浏览器缓存 600 秒

答案:B

解析:s-maxage 在共享缓存(CDN)中优先级高于 max-age,因此 CDN 节点采用 600 秒;s-maxage 对私有缓存(浏览器)无效,浏览器回退使用 max-age 的 7200 秒。这一组合实现了“CDN 频繁回源检查更新,浏览器长期缓存减少请求”的典型策略。

3.7 应用边界

s-maxage 并非在所有场景中都适用,理解其边界条件才能避免误用:

维度 说明
适用场景 CDN 加速、反向代理(Nginx / Varnish)、API 网关、微服务边缘代理等共享缓存节点
不适用场景 纯浏览器本地缓存、Service Worker 缓存(属于私有缓存),s-maxage 会被忽略
前置条件 共享缓存节点必须严格遵循 HTTP/1.1 缓存规范;部分老旧的代理设备可能不支持 s-maxage
与 no-cache / no-store 的交互 如果同时存在 no-cache 或 no-store,s-maxage 将被覆盖,共享缓存不会存储响应
最佳实践 始终同时设置 max-age 和 s-maxage,且 s-maxage 值通常小于 max-age;需要共享缓存立即过期时可设 s-maxage=0
经验法则:在配置 CDN 时,将 s-maxage 视为“CDN 的 TTL”,将 max-age 视为“浏览器的 TTL”。两者独立设置,互不干扰,共同构建分层缓存体系。