# VOD 深度剖析（七）：CDN 分发 —— 为什么它在全球都快

> CDN 架构（Edge/Shield/Origin）、缓存策略、请求合并、签名 URL、预热、JIT 与预打包、多 CDN 策略、HTTP/3 以及成本估算。

- 作者: zhuermu
- 发布: 2026-05-10
- 网页版: https://zhuermu.com/blog/vod-deep-dive-part-7-cdn-distribution/

---
> *这是 [VOD 流媒体深度剖析](/blog/vod-deep-dive-part-1-video-fundamentals/) 系列的第 7 篇。*

---

## 为什么视频需要 CDN

假设你的服务器在上海，而一位美国用户想要观看：

```
US user ────🌊 Trans-Pacific undersea cable 🌊────► Shanghai server
                  (180ms+ latency)
                  (high packet loss)
                  (limited bandwidth)
```

10 万名美国用户并发观看，每人 2 Mbps = **200 Gbps 的跨洋流量**。无论从技术还是财务上都不可行。

**CDN（内容分发网络）** 解决了这个问题：

```
              ┌─── New York edge cache ──► US users (20ms)
Shanghai ───►
origin        └─── Frankfurt edge cache ──► EU users (10ms)

After the first origin fetch, popular videos "live" at global edge nodes
```

可以把 CDN 想象成一条 **全球连锁便利店**。总部（源站）在一处集中生产商品，然后分发到每座城市的门店（边缘节点）。用户就近购买 —— 更快也更便宜。

---

## 三层架构

```
 ┌─────────────────────────────────────────┐
 │            User                         │
 └──────────────┬──────────────────────────┘
                │ ① Request seg_42.m4s
                ▼
       ┌────────────────────┐
       │ Edge PoP           │   Closest to user, within tens of km
       │ (hundreds globally)│   Caches popular content
       └────────────┬───────┘
                    │ Cache miss → go upstream
                    ▼
       ┌────────────────────┐
       │  Mid-tier / Shield │   Regional aggregation layer
       │  (a few per region)│   Reduces origin load
       └────────────┬───────┘
                    │ Cache miss → origin fetch
                    ▼
       ┌────────────────────┐
       │      Origin        │   Object storage (S3/OSS/COS)
       │                    │   or Packager service (MediaPackage)
       └────────────────────┘
```

**缓存命中率（Cache Hit Ratio）** 是 CDN 最重要的指标。目标：**> 95%**。

---

## 回源流程

```
1. User → Edge: GET /video/seg_42.m4s
2. Edge checks local cache:
   ├── HIT → return immediately ✅
   └── MISS:
       3. Edge → Shield: GET /video/seg_42.m4s
       4. Shield checks cache:
          ├── HIT → return to Edge → Edge caches → return to user
          └── MISS:
              5. Shield → Origin: GET /video/seg_42.m4s
              6. Origin responds → Shield caches → Edge caches → user
```

第一位用户会触发整条链路（慢）。之后的每位用户都命中边缘缓存（快）。这就是为什么 **新上线剧集的第一位观众体验最差** —— 也是预热之所以重要的原因。

---

## 缓存策略

CDN 的缓存行为由 HTTP 头控制：

### 推荐的 VOD 缓存策略

| 文件类型 | Cache-Control | 理由 |
|-----------|--------------|-----------|
| **清单文件**（.m3u8/.mpd） | `max-age=60` 到 `max-age=300` | 可能更新（广告插入、字幕变更） |
| **初始化分片**（.mp4） | `max-age=31536000`（1 年） | 不可变 |
| **媒体分片**（.m4s/.ts） | `max-age=31536000`（1 年） | 不可变 |
| **字幕**（.vtt） | `max-age=3600`（1 小时） | 可能被修订 |
| **缩略图** | `max-age=86400`（1 天） | 可能更新 |

**关键陷阱**：如果签名 URL 的参数（`?token=xxx`）被纳入缓存键，那么 **每个用户都会得到一个唯一的缓存条目，命中率会跌到零**。务必将签名参数从缓存键中排除。

---

## 请求合并（Request Collapsing）

当 100 个用户同时请求 `seg_42.m4s` 且全部缓存未命中时：

**没有合并**：100 个回源请求 → 源站过载。

**启用合并**（现代 CDN 默认开启）：边缘节点识别出这是同一个对象，只发送 **1** 个回源请求，然后把响应分发给全部 100 个用户。

在上线活动和新剧首播时，这是救命稻草。

---

## 签名 URL 与防盗链

CDN 的分片 URL 是公开的。有人可能把它们嵌入自己的网站免费白嫖。**签名 URL** 可以防止这一点：

```
https://d1234.cloudfront.net/video/seg_42.m4s
  ?Expires=1715084800
  &Signature=nitfHRCrtziwO2HwPf...
  &Key-Pair-Id=APKAEIBAERJR2EXAMPLE
```

CDN 边缘节点会校验：是否已过期？签名是否正确？参数是否被篡改？校验失败 → 403 Forbidden。

其他防盗链手段：Referer 白名单、User-Agent 检查、IP 地域限制、限流，以及 **签名 Cookie**（在需要加载大量分片时比签名 URL 更方便）。

---

## 预热（Pre-Warming）

新剧上线时，所有分片都是 **冷的**（尚未进入边缘缓存）。首波用户全部未命中 → 体验糟糕。

**预热**：在 CMS 发布之后，主动把内容推送到边缘节点：

```
CMS publish hook → CDN prewarm API
  ├── POST /prewarm { urls: ["…/seg_0001.m4s", ..., "…/seg_0010.m4s"] }
  └── CDN dispatches edge nodes to origin-fetch

Minutes later: global edges have the segments
First-wave users hit cache ✅
```

不要预热每一个分片 —— 重点关注：初始化分片、前 5–10 个媒体分片，以及这些分片对应的所有清晰度档位。

---

## JIT 打包 vs 预打包

### 预打包（离线）

在转码之后生成所有 HLS/DASH/CMAF 清单和分片 → 存入 S3 → CDN 直接提供。

**优点**：简单，缓存命中率最高。**缺点**：存储成本更高（多种格式的多份拷贝），不够灵活（加一条字幕就得重新打包）。

### JIT 打包（Just-in-Time，即时打包）

S3 只存储源 fMP4。当用户请求清单时，源站服务实时生成。

**优点**：只存一份，灵活（无需重新打包即可添加 DRM 或字幕）。**缺点**：首次命中较慢（消耗源站 CPU），源站必须扛住负载。

**代表性实现**：AWS MediaPackage-VOD、Unified Origin、开源的 mp4box。

**建议**：小体量片库 + 高流量 → 预打包。大体量片库 + 长尾内容 → JIT 打包。

---

## 多 CDN 策略

为什么单个 CDN 不够用：

- **单点故障**：CDN 挂了，你也就黑屏了
- **地理覆盖**：没有任何一家 CDN 在所有地区都是最好的
- **议价能力**：多家厂商为你的业务相互竞争
- **性能**：随时把流量路由到当下最快的那家

### 路由方式

**基于 DNS**：70% 流量到 CloudFront，20% 到 Cloudflare，10% 到区域性 CDN。

**客户端探测**：App 在启动时 ping 所有 CDN，选出最快的一家；每 5 分钟重新探测一次。

**托管调度**：Cedexis、Conviva Traffic Steering、Route 53 基于延迟的路由。

### 故障转移

播放器逻辑：如果 CDN A 连续失败 3 次 → 切换到 CDN B → 上报告警。

---

## HTTP/2、HTTP/3 与 QUIC

| 协议 | 对视频的关键收益 |
|----------|---------------------|
| **HTTP/1.1** | 基准。队头阻塞（Head-of-line blocking）是主要瓶颈。 |
| **HTTP/2** | 多路复用：单条 TCP 连接上并发请求。对下载多个分片是重大改进。 |
| **HTTP/3 / QUIC** | 基于 UDP。消除了 TCP 队头阻塞。0-RTT 重连。**在弱网/高丢包的移动网络上带来显著提升。** |

所有主流 CDN（CloudFront、Cloudflare、Akamai）都支持 HTTP/3。启用它可以改善启动时间和重缓冲率，在蜂窝网络上尤为明显。

---

## 成本估算

### 典型带宽定价（批量折扣后）

| 地区 | $/GB |
|--------|------|
| 北美 / 欧洲 | $0.005–$0.010 |
| 拉丁美洲 | $0.020–$0.050 |
| 中东 | $0.050–$0.080 |
| 亚太 / 印度 | $0.015–$0.040 |

### 快速估算

```
Assumptions:
  DAU = 1 million
  Average watch time = 30 min/day
  Average bitrate = 1.2 Mbps (720p H.264)

Per-user daily traffic = 1.2 Mbps × 1800s ÷ 8 ≈ 270 MB
Daily total = 1M × 270 MB = 270 TB
Monthly total = 270 TB × 30 = 8.1 PB

At $0.02/GB (weighted average):
  Monthly CDN cost ≈ 8.1 PB × 1000 × $0.02 = $162,000
```

### 降本手段

1. **更优的编解码器**：HEVC 相比 H.264 节省 37%；AV1 再省 20–30% → **直接压缩账单**
2. **逐标题编码（Per-title encoding）**：为每个标题定制码率阶梯，节省 10–20%
3. **降低默认档位**：移动端默认 720p（相比 1080p 节省 40%）
4. **多 CDN 竞价**
5. **批量折扣**：> 1 PB/月 可解锁可观的折扣档位
6. **自建 CDN**：Netflix Open Connect 把服务器直接部署在 ISP 数据中心内

---

## 关键要点

1. CDN = 把内容缓存到离用户最近的「便利店」里。
2. 三层架构：**Edge → Shield → Origin**。
3. **缓存命中率 > 95%** 是目标。把签名参数排除在缓存键之外。
4. **对新内容预热**，避免首波冷未命中。
5. **JIT 打包** 节省存储；**预打包** 更简单。
6. **多 CDN** 提升韧性、覆盖范围和议价能力。
7. **HTTP/3** 显著改善弱网性能。
8. CDN 带宽是 VOD 的主要成本大头：**编解码器效率 + 档位设计 + 多 CDN 竞价** 是三个最大的杠杆。

---

*上一篇：* [第 6 篇：自适应码率流媒体](/blog/vod-deep-dive-part-6-adaptive-bitrate-streaming/)

*下一篇：* **[第 8 篇：DRM 内容保护](/blog/vod-deep-dive-part-8-drm-content-protection/)**

---

## 常见问题

### 视频网站为什么一定要用 CDN？

单一源站扛不住视频流量：10 万人并发、每人 2 Mbps 就是 200 Gbps 的跨洋带宽，远端用户延迟还高达 180ms 以上，技术和成本上都不可行。CDN 把热门内容缓存到全球数百个边缘节点，首次回源之后，用户就近从缓存下载分片，延迟只有几十毫秒。最核心的指标是缓存命中率，目标应高于 95%。

### HLS 的分片和 m3u8 清单应该设置多长的 CDN 缓存时间？

媒体分片和初始化分片是不可变的，可以缓存一年（max-age=31536000）；清单文件（.m3u8/.mpd）可能因广告插入、字幕变更而更新，建议 max-age=60 到 300；字幕缓存约 1 小时，缩略图约 1 天。特别注意：签名 URL 的参数（如 ?token=）必须从缓存键中排除，否则每个用户都是独立缓存条目，命中率会直接跌到零。

### JIT 打包和预打包该怎么选？

预打包是转码后一次性生成所有 HLS/DASH/CMAF 清单和分片存入对象存储，简单且缓存命中率最高，但多份格式拷贝费存储，加条字幕就要重新打包。JIT（即时打包）只存一份源 fMP4，用户请求时由源站实时生成清单，灵活省存储，但首次命中较慢、源站要扛住负载。经验法则：小片库高流量选预打包，大片库长尾内容选 JIT。


---

## 参考资料

- [Amazon CloudFront Developer Guide](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) — AWS Documentation
- [Amazon S3 User Guide](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html) — AWS Documentation
