跳到内容

7.2 CDN 缓存、回源与流量导向

远方居民下载同一份地图时,源站已经不堪重负;你们要决定哪些副本可以放到离用户更近的边缘节点。

CDN 是分布式 edge platform,caching 是它最常见的能力之一。它可以缩短 user 与 content copy 之间的 network path、减少 origin load,并在 edge 处理 TLS、request routing 和部分 security policy。但这些效果取决于 cacheability、traffic mapping 和 origin design,不是“接入 CDN 就自动快”。

1. 一次 edge request 的基本路径

text
client
  |
  | DNS answer / anycast route
  v
edge point of presence
  |-- fresh cache hit -----------------> response
  |-- stale entry -> revalidate origin -> 304 / new response
  `-- miss ----------------------------> origin or origin shield

CDN 不一定先“把所有 file 推到全球”。很多 content 在第一次 request 到达 edge 时 pull from origin,后续 request 才命中 cache;大规模 launch 或 video workflow 也可以做 pre-positioning。

2. Cache key 决定“哪些 request 共享一份 response”

Typical key 至少包含 scheme/host/path,query parameter 是否进 key 取决于 configuration。Vary 让 cache 按指定 request field 区分 stored response,例如 content encoding 或 language。

一个 cache key 过窄可能把 user A 的 personalized response 发给 user B;过宽则把每个 tracking query、cookie 或 header 变体分成独立 object,让 hit ratio 降低并放大 storage。

Cache policy 应明确:

  • 哪些 method/status 可存;
  • shared cache 是否允许存 authenticated/personalized response;
  • key 包含哪些 query/header/cookie dimension;
  • Cache-ControlExpiresETagLast-Modified 如何处理;
  • stale response 在 origin error/revalidation 期间能否使用;
  • maximum object size 与 negative/error caching policy。

3. Freshness、validation 与 purge 是三件事

Fresh response 可不问 origin 直接复用。Stale response 可用 validator 发 conditional request;origin 返 304 时 cache 更新 metadata 并继续使用 stored content。

Purge/invalidation 是 CDN vendor control plane 能力,不是 HTTP caching 语义保证的全球 instant transaction。Purge 需要传播时间,也可能因 key 与预想不同而没命中 object。

Static asset 通常适合 content-addressed / versioned URL:

text
/assets/app.4f3a91c2.js

Content 变更就生成新 URL,旧 URL 可设 long freshness lifetime。HTML entry point 用较短 freshness 或 validation,引用新 asset URL。这比每次 release 都要精准 purge 全球旧 object 更容易推理。

4. Miss storm 与 origin shield

一个 popular object 过期时,大量 edge/request 可同时回源,形成 cache stampede。常见缓解方法:

  • request collapsing / single flight:同一 key 只让一个 fetch 回源;
  • freshness jitter:避免大量 object 同一时刻过期;
  • stale-while-revalidate / stale-if-error 策略;
  • origin shield:多个 edge 先向一层 shield cache 聚合 miss;
  • origin capacity limit 与 circuit breaker。

Shield 是多一跳,它的价值来自 miss aggregation 和 origin protection,不是每个 request 都会 latency 更低。

5. Geo-aware DNS 与 anycast 都不承诺“地理最近”

CDN 可通过 DNS answer 将 recursive resolver/client subnet 映射到某个 edge cluster,也可让多个 site 广播同一 anycast IP,由 BGP route selection 选 path。实际部署常将多种 mechanism 组合。

GeoDNS 看到的常是 recursive resolver address,不一定是 end user address;EDNS Client Subnet 可传递部分 client prefix,但带来 privacy 和 cache fragmentation trade-off。DNS answer 还会在 TTL 内被 cache,不能做 per-request instantaneous load decision。

Anycast 选的是 routing policy 下的 best path,不是 Euclidean distance 最短或 latency 必然最低的 site。BGP 本身也不读 CDN application queue depth。Operator 可通过 route advertisement/withdrawal、community 和 traffic engineering 影响 mapping,但需要另外的 health signal 与 failover design。

6. 观测 cache,不要靠 vendor header 猜品牌

bash
curl -sS -D - -o /dev/null https://www.example.com/assets/app.js

关注:

  • Cache-ControlExpiresETagLast-Modified
  • Age 是 response 在 cache 系统中的 current age 信息,不是“命中某 CDN 品牌”的证据;
  • ViaServer-Timing 或 vendor-specific cache-status header,其语义应查该 provider 文档;
  • Response 是 HITMISSBYPASSSTALE 还是 revalidated;
  • Request ID / trace 能否与 origin log 关联。

只从 response header 搜索 cf-x-cache 之类字符串不能可靠判断“是否使用 CDN”:header 可被删除、修改或由其他 proxy 生成。

7. Cache correctness 与 security

CDN 是 shared intermediary,cache policy error 可放大 data leak。重点检查:

  • Authenticated/private response 是否被 shared cache 存储;
  • Cache key 是否忽略会改变 response 的 header/cookie/query;
  • Untrusted host/header 是否能污染 generated redirect 或 absolute URL;
  • Origin 是否只允许受信 CDN 访问,以及如何 authentication edge-to-origin;
  • Signed URL/cookie 的 expiry、scope 和 key rotation;
  • Compression/range request 与 object size limit 是否可被 abuse。

TLS 在 client-to-edge 终止时,edge 能看见 plaintext,才能做 HTTP caching/routing。Edge-to-origin 是另一条 security boundary,需要自己的 TLS authentication、authorization 和 certificate lifecycle。

8. 验收问题

  1. 为 versioned JS asset 和 HTML entry point 分别设计 cache policy。
  2. 为什么 Age 不能单独证明 response 来自某个 CDN?
  3. 解释 cache key 过窄与过宽各自的 failure mode。
  4. 为一个 hot object 的 expiry 设计 request collapse、stale policy 和 origin shield。
  5. 为什么 anycast 不等于 application-aware load balancing?

下一课进入7.3 负载均衡算法、健康检查与重试边界

参考

Built with VitePress | Software Systems Atlas