第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 在不同缓存层级中的生效位置:
3.4 类比理解
想象一下公司的公共冰箱和你的个人办公桌抽屉:
- 个人抽屉(私有缓存)——你放了一份便当,贴上标签“保质期 3 天”(
max-age)。只有你自己会取用,保质期完全由你决定。 - 公共冰箱(共享缓存)——所有同事都能打开,行政部统一管理,在冰箱门上贴了告示:“所有公共食材保质期 1 天”(
s-maxage)。即使便当盒上写的是 3 天,在冰箱里也按 1 天执行。
这个例子清晰地说明了:同一个物品在不同“缓存层”可以遵循不同的过期规则。s-maxage 就是行政部给公共冰箱定下的统一规则,优先级高于个人标注。
3.5 常见误区
注意:以下误区在实际项目中经常导致缓存策略失效,需要特别警惕。
- 误区一:s-maxage 可以完全替代 max-age
只设置s-maxage而不设置max-age,会导致浏览器无法获得明确的缓存时长,可能回退到启发式缓存。正确的做法是两者同时设置,各司其职。 - 误区二:s-maxage 在浏览器中也生效
部分开发者以为s-maxage是一个“更强的 max-age”,在所有地方都生效。实际上浏览器会完全忽略s-maxage,只认max-age或Expires。 - 误区三:s-maxage 优先级永远高于 max-age
优先级的高低取决于缓存类型。在共享缓存中s-maxage确实覆盖max-age,但在私有缓存中s-maxage根本不参与比较。 - 误区四: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”。两者独立设置,互不干扰,共同构建分层缓存体系。