注:本文基于模型知识整理,建议结合权威教材与 RFC 原文核对细节。
一句话定义
CDN(content delivery network,内容分发网络)把内容缓存到离用户最近的边缘节点,与正向/反向代理和 HTTP 缓存机制配合,用「就近命中」对抗物理距离带来的延迟。
为什么重要
光在光纤中的传播速度有上限,跨洋往返时延(RTT)是物理量,软件优化无法把它压没(回扣 kp-002《性能指标与时延模型》的时延构成)。要快只有两条路:减少往返次数、缩短物理距离——HTTP 缓存与 CDN 正是这两条路的工程化。现代网站的静态资源、视频与 API 加速几乎都架在 CDN 之上,读懂 Cache-Control 是前后端与运维的共同必修课。
前置知识
建议先读 kp-023《HTTP》,掌握报文结构、304 状态码与无状态语义;建议回看 kp-002《性能指标与时延模型》中传播时延、往返时延的讨论,理解「物理定律」这一前提。
核心概念
- CDN 原理三步:边缘部署——源站内容被复制或缓存到全球各地的边缘节点;DNS 调度——GSLB(global server load balance,全局负载均衡)在解析域名时按用户来源返回最近或最优的边缘节点 IP;回源——边缘未命中时向源站取一次数据并缓存(origin pull),后续请求就地命中。
- 代理三兄弟(方向决定角色):正向代理替客户端出头,服务器只见代理不见真实客户端(内网统一出口、科学上网);反向代理替服务器接客,客户端只见代理不见真实后端(Nginx、负载均衡、API 网关入口);透明代理部署在网络路径上、对通信两端不可见(运营商缓存或审计)。
- 强缓存与协商缓存:强缓存由 Cache-Control: max-age=N 声明,有效期内浏览器根本不发请求;no-cache 不是「不缓存」而是「可存但每次需协商」,no-store 才是彻底不存。协商缓存用 ETag/If-None-Match 或 Last-Modified/If-Modified-Since,由服务器比对,未变则回 304——省的是响应体流量,不省这一次请求本身。
- 缓存层级链:浏览器(内存/磁盘)缓存、CDN 边缘缓存、中间层与源站。命中率(直接命中返回的请求占比)是核心指标:层级越靠前命中,延迟越低、回源越少。
图示
CDN 的调度与回源路径,以及缓存层级:
用户 ──域名解析──▶ GSLB(按用户来源就近调度,返回边缘 IP)
用户 ──HTTP 请求──▶ 边缘节点 ──命中──▶ 直接返回(延迟最低)
边缘节点 ──未命中──▶ 回源 origin pull ──▶ 源站
(取回后在边缘缓存,再返回用户)
缓存层级:浏览器缓存 ──▶ CDN 边缘缓存 ──▶ 源站
(越靠前命中越快;未命中的请求逐级向后穿透)原理与机制
协商缓存的完整交互:
GET /app.js HTTP/1.1
Host: cdn.example.com
If-None-Match: "v-a1b2c3"
HTTP/1.1 304 Not Modified
ETag: "v-a1b2c3"服务器比对 If-None-Match 与当前内容的 ETag:一致说明没变,回 304 空体,浏览器继续用本地副本;不一致则回 200、新内容与新 ETag。相比 Last-Modified 只有秒级精度、且无法表达「改回旧内容」,ETag 更精确,两者常并用;集群环境下 ETag 生成算法必须跨节点一致,否则同一文件在不同节点算出不同值,缓存会反复失效。
失效与预热。 主动失效:源侧内容更新后,通过 CDN 的 purge/刷新接口清除边缘缓存,或缩短 TTL 让其自然过期;预热:大版本发布或大促前,提前把热点 URL 拉到边缘,避免开闸后第一波请求全部回源——回源风暴足以打挂源站。
实例分析
最佳实践:静态资源文件名带内容指纹(如 app.a1b2c3.js,构建时按内容哈希命名),并配置 Cache-Control: max-age=31536000, immutable(一年,期内不协商);HTML 文件本身用很短的 max-age 或 no-cache。效果:HTML 每次都能及时拿到最新版本,其中引用的资源 URL 随版本变化(新指纹),旧缓存自动作废、新文件长期缓存——改版本即失效,兼顾速度与新鲜度。
常见误区
- 304 不是「没有发生请求」:请求照发,只是没有响应体;强缓存有效期内才是真的不发请求。
- no-cache 与 no-store 混淆:前者是「每次协商验证」,后者才是「彻底不存」。
- CDN 命中率高不等于体验一定好:回源路径慢、边缘冷节点、动态内容不可缓存都会拖后腿。
- 给 HTML 设长缓存是灾难:用户会长期拿到旧页面,引用的还是旧指纹资源,改版等于失效。
自测题
- 强缓存与协商缓存的区别是什么?
答案要点: 强缓存(Cache-Control: max-age)在有效期内浏览器完全不发请求;协商缓存每次都要发请求,携带 If-None-Match/If-Modified-Since 由服务器比对,未变返回 304(省响应体、不省请求),变了返回 200 与新内容。
- 正向代理与反向代理的方向区别是什么?
答案要点: 正向代理站在客户端一侧,替客户端访问服务器,服务器看不到真实客户端;反向代理站在服务器一侧,替后端接收请求,客户端看不到真实服务器(如 Nginx、负载均衡)。
- CDN 如何把用户引导到最近的边缘节点?
答案要点: 通过 DNS 调度:GSLB 在权威解析时按用户来源(通常是本地 DNS 的位置)返回最近或最优边缘节点的 IP,用户随后直接访问该边缘。
- 为什么静态资源要用「内容指纹文件名 + 一年 max-age」?
答案要点: 内容变则文件名(哈希指纹)变,URL 变了缓存自然失效,无需等 TTL 或手动刷新;指纹不变的旧文件可放心超长缓存并标 immutable,兼顾极致缓存与版本新鲜度。
- 大促或发布前为什么要做「预热」?
答案要点: 边缘节点初始为冷缓存,开闸后第一波请求会集中回源,可能打垮源站;提前把热点内容拉到边缘,让首波请求就地命中,避免回源风暴。
延伸阅读
- 《Web 性能权威指南》(Ilya Grigorik)
- RFC 9111(HTTP Caching)