用户登录

技术文章

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

HTTP 缓存与 CDN 加速实践:缓存键、校验与回源责任怎么划

一句话回答

缓存与 CDN 的收益来自减少回源,但正确性取决于三件事:响应能否被共享缓存存储、缓存键是否覆盖影响内容的所有请求维度、过期后由谁校验或失效。本文按 RFC 9111 的通用语义解释 max-age 与 s-maxage 的作用范围、no-cache 与 no-store 的区别、Vary 与 CDN 缓存键不一致的风险,以及 ETag 条件请求在其中的位置;具体 CDN 厂商的默认 TTL、清除时效与命中判定字段本次无资料,标为待核实。

要让 HTTP 缓存与 CDN 真正加速,先要回答三个问题,而不是先调 TTL:这个响应允许被谁存储?哪些请求算“同一个资源”?过期之后由谁负责校验或失效?这三件事没定清楚,加缓存只是把错误的内容更快地发给更多人。本文只讲协议层面的通用口径;具体 CDN 产品的默认 TTL、清除生效时间、命中判定字段,本次没有可核验资料,均标为待核实。

一、先分清三种缓存归属#

HTTP 缓存(HTTP Caching,语义见 IETF 的 RFC 9111)把缓存分为私有缓存与共享缓存。浏览器缓存属于私有,CDN 边缘节点属于共享。同一个响应头在不同归属下效果不同:

  • private:只允许私有缓存存储,共享缓存不应保存。
  • s-maxage:只对共享缓存生效,并优先于 max-age;它同时带有要求共享缓存过期后必须校验的语义。
  • no-store:任何缓存都不应存储。
  • no-cache:允许存储,但每次使用前必须向源站校验。常见误读是把它当成“不缓存”,实际是“存但必校验”。

把 no-cache 写成 no-store,命中率会被自己砍掉;反过来把该私有的响应写成 max-age,共享缓存就会替你把个性化内容发给别人。

二、缓存键:Vary 与 CDN 键配置必须对齐#

Vary 声明哪些请求头参与“选哪个缓存条目”。常见维度是 Accept-Encoding(压缩格式)、Accept-Language,以及业务自定义的地区、设备标记。少写一个维度,就会出现“同一 URL 返回了另一种变体”。

两个容易错的点:

  • Authorization:带该请求头的请求,共享缓存默认不得存储其响应,除非响应显式声明 public、s-maxage 或 must-revalidate。这是协议层面的限制,不是厂商策略。
  • Set-Cookie:协议并未禁止缓存含该头的响应,但只要被共享缓存复用,会话标识就可能落到别的用户手里。实践上应配 private 或 no-store,而不是依赖边缘节点“应该会跳过”。

还要注意:Vary 是源站表达,CDN 的缓存键是边缘侧配置,两者是两套机制。若边缘键只看 URL 而源站按 Vary 分发变体,就会出现源站认为不同、边缘认为相同的错配。各家键配置项的粒度与上限需查对应文档,此处待核实。

三、新鲜期、校验与失效#

指令作用对象语义要点
max-age私有与共享缓存相对响应生成时间的新鲜期
s-maxage仅共享缓存覆盖 max-age,过期后须校验
must-revalidate所有缓存过期后不得使用陈旧副本
stale-while-revalidate支持者来自 RFC 5861,非核心规范;先给旧值、后台刷新,需两端支持

过期之后走条件请求:源站用 ETag / If-None-Match 或 Last-Modified / If-Modified-Since 判断是否变化,未变则返回 304,不重传正文。ETag 的强弱语义会影响范围请求与内容合并的判断,改动响应体生成逻辑时要同步考虑 ETag 是否还成立。

四、CDN 侧的四个判断条件#

  1. 可缓存内容占比决定命中率上限。登录态接口、实时库存这类响应通常不该进共享缓存,调 TTL 也救不回来。
  2. 回源成本不只在带宽:压缩是否在边缘完成、连接是否复用、TLS 在哪一层终止,都会影响缓存能否读到明文请求头来做键决策。
  3. 清除(purge)是兜底而非常规手段。如果发布流程依赖“发完再清缓存”,说明 TTL 与文件名版本化策略没设计好。
  4. 观测要看命中而非只看平均耗时。标准字段是 Age(响应在缓存中已存在的估算时长);命中标记多为厂商自定义响应头,字段名与含义待核实。

五、核对示例(未执行)#

下面只是查看响应头的命令骨架,使用占位域名 example.com,本文未实际执行,因此不给出任何输出结果。

curl -sI https://example.com/static/app.js

拿到响应后逐项核对:Cache-Control 是否区分了私有与共享、是否误用 no-store;Vary 是否覆盖了实际影响内容的请求头;ETag 是否存在且与内容一致;Age 是否说明请求确实命中了中间缓存。

六、边界#

本文没有涉及具体 CDN 厂商的配置面板、边缘计算、动态加速与 ESI 等能力,这些必须以厂商文档为准。最终判据不是命中率数字,而是“错误内容被复用的代价”:可公开的静态资源可以给长 TTL 加文件名指纹;涉及身份与权限的响应,宁可少缓存,也不要把判断权交给默认配置。

作者:沐小悠

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

更多文章 GET 示例接口

「」标签下的其他文章