用户登录

技术文章

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

API 响应的 HTTP 缓存与 CDN 加速:缓存键、失效回源与验证顺序

一句话回答

CDN 加速 API 的前提不是调大 TTL,而是先判定哪些响应可进入共享缓存、用什么缓存键区分、失效后如何回源。文章给出按响应头判定可缓存性的顺序、缓存键纳入参数的方式、失效与回源的降级路径,以及一条可复现的响应头验证顺序;具体 CDN 供应商的失效接口与扩展指令支持情况需按官方文档核实。

给 API 加 CDN,收益通常来自“少回源”,风险则来自“缓存了不该共享的东西”。所以顺序应该是:先用响应头把可缓存边界写清楚,再决定缓存键,最后定义失效与回源的保护措施。TTL 数值是最后一步,不是第一步。

一、先判定响应能否进入共享缓存#

可缓存性由请求方法、状态码和响应头共同决定,不由 CDN 配置单方面决定。GET、HEAD 在语义上可被缓存,其他方法默认不进入缓存;具体状态码的默认可缓存性,以及各指令的精确含义,以 IETF 的 HTTP 缓存规范(RFC 9111)官方文本为准,本文未联网核对条款细节。

指令概括含义对 API 的实际影响
no-store不得存储最严格的排除,适合含敏感字段的响应
no-cache可存储,但复用前须向源站验证不是“不缓存”,误读会低估回源量
private仅私有缓存可存用户态响应应显式标注,避免中间层留存
public允许共享缓存存储只是许可,仍需其它条件成立
max-age新鲜期对共享缓存与浏览器都生效
s-maxage仅共享缓存生效,并覆盖 max-ageCDN 与浏览器的生命周期分离时的主要手段
must-revalidate过期后不得使用陈旧副本余额、库存等强一致场景

判定顺序建议固定下来:先看是否显式禁止存储,再看是否带 Set-Cookie 或授权相关信息,最后才看新鲜期。带 Authorization 的响应默认不进入共享缓存;如果确实需要,应显式声明并确认这不会造成跨用户复用,这一条比任何 TTL 都重要。

二、缓存键决定了命中率,也决定了串号风险#

缓存键的常见默认构成是主机名、路径与查询串。问题往往出在两个方向:一是把全部查询参数纳入键,导致分页游标、时间戳等噪声参数让命中率接近零;二是为了提升命中率把鉴权类参数从键里移除,于是不同用户的响应互相覆盖。

可操作的做法是用白名单声明参与键的参数,把埋在查询串里的业务维度(如语言、版本、租户)显式保留,其余参数在边缘层剥离或规范化。同时用 Vary 声明响应随哪些请求头变化,例如按 Accept-Encoding;但不要滥加,每个 Vary 维度都会切分缓存空间。个性化响应更稳妥的选择是不进共享缓存,而不是靠键去隔离。

三、失效与回源:先定义降级路径#

  • 主动失效(purge)的接口形态、粒度(按 URL、按标签、按目录)与配额,因供应商而异,需按其官方文档核实,本文不作假设。
  • stale-while-revalidate、stale-if-error 等陈旧内容扩展指令支持度同样取决于边缘实现,启用前应确认行为。
  • 批量失效后会出现集中回源,源站需要限流与请求合并;阈值应通过压测确定,不要照搬他人的数字。

四、用响应头做一次可复现的验证#

下面的命令只是查看响应头的示例,本次未执行,域名与路径均为占位,请替换为你的实际环境:

# 未执行示例:连续三次请求同一 URL,观察 Age 是否递增
curl -sSI "https://api.example.com/v1/items?lang=zh" | grep -iE "cache-control|age|vary|x-cache|etag"

判断要点:Cache-Control 是否与你的契约一致;Age 在三次请求间是否增长,增长说明命中了共享缓存;Vary 是否只包含你打算切分的维度。X-Cache 一类命中标记属于供应商自定义头,名称与取值需按其文档核实,不能作为通用判据。

五、边界条件#

带用户身份的响应、实时价格与库存、A/B 实验分流、按请求头返回不同结构的内容,都不适合直接进入共享缓存。若业务要求缓存,应先把这些响应拆分到独立路径,再单独设计策略。另外,浏览器缓存与 CDN 缓存是两层,用 s-maxage 分离两者时,要确认中间层不会回退到 max-age。

本文涉及的供应商失效接口、扩展指令支持情况与回源限流阈值均待核实;在没有官方文档与自有压测记录之前,不宜把上述任何一项写成固定配置。

作者:沐小悠

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

更多文章 GET 示例接口

「」标签下的其他文章