第 7 章 · CDN 分发:为什么全球打开都很快
VOD 流媒体技术全解 · 第 7 章(共 12 章)· 预计阅读 20 分钟
本章你会理解:CDN 是什么、为什么视频必须上 CDN、边缘/中转/源站三层结构、签名防盗链、多 CDN 调度、以及一个 VOD 平台的 CDN 账单大概长什么样。
假设你在上海搭了一台服务器放视频,美国用户来看:
美国用户 ────🌊 跨太平洋海底光缆 🌊────► 上海服务器
(延迟 180ms+)
(丢包率高)
(带宽受限)
每个美国用户每秒从你的上海服务器拉 2 Mbps 视频,10 万美国并发用户 = 200 Gbps 跨国出口。这在技术和成本上都不可能。
CDN(Content Delivery Network,内容分发网络) 解决方案:
┌─── 美国纽约缓存节点 ───► 美国用户(延迟 20ms)
上海源站 ────►
└─── 法兰克福缓存节点 ───► 欧洲用户(延迟 10ms)
第一次回源后,热门视频就"驻扎"在全球节点里
💡 类比:CDN 像全球连锁便利店。总部在一个地方生产商品(源站),但分销到每个城市的便利店(边缘节点)。用户就近购买,既便宜又快。
典型 CDN 架构:
┌─────────────────────────────────────────┐
│ 用户 (User) │
└──────────────┬──────────────────────────┘
│ ① 请求 seg_42.m4s
▼
┌────────────────────┐
│ Edge PoP(边缘节点)│ 离用户最近、几十公里内
│ (全球数百个) │ 缓存热门内容
└────────────┬───────┘
│ 缓存 miss ? 回源
▼
┌────────────────────┐
│ Mid-tier / Shield │ 中间层,聚合多个边缘的回源请求
│ (每地区几个) │ 减轻源站压力
└────────────┬───────┘
│ 缓存 miss ? 回源
▼
┌────────────────────┐
│ Origin │ 源站:对象存储 (S3/OSS/COS)
│ (S3、自建机房) │ 或 Packager 服务 (MediaPackage)
└────────────────────┘
三个概念:
• Edge(边缘):离用户最近的缓存层。用户请求先到这里。
• Mid-tier / Shield(中转层):省钱和稳源。多个边缘 miss 时汇聚到一个 shield 节点,再去源站。
• Origin(源站):真正存所有内容的地方。通常是对象存储(S3、OSS、COS)或一个打包服务。
📌 缓存命中率(Cache Hit Ratio) 是 CDN 最重要的指标。越高越省钱、越快。目标 > 95%。
用户请求一个切片的完整流程:
1. 用户 → Edge: GET /video/seg_42.m4s
2. Edge 查本地缓存:
├── 命中 (HIT) → 直接返回 ✅ 用户拿到切片
└── 未命中 (MISS):
3. Edge → Shield: GET /video/seg_42.m4s
4. Shield 查缓存:
├── 命中 → 回给 Edge → Edge 缓存并回给用户
└── 未命中:
5. Shield → Origin: GET /video/seg_42.m4s
6. Origin 响应 → Shield 缓存 → Edge 缓存 → 用户
一个切片的命运:
• 第 1 个用户触发 MISS → 全链路回源 → 慢(多几百 ms)
• 第 2-N 个用户在 Edge 命中 → 快(几十 ms)
• 缓存 TTL 到期后下一个用户再 MISS
这就是为什么"新剧刚上架第一个用户体验最差",也就是下面要讲的"预热"要解决的问题。
7.4
缓存策略:TTL、Cache-Control
CDN 怎么知道一个文件能缓存多久?看 HTTP 头。
HTTP/1.1 200 OK
Content-Type: video/iso.segment
Cache-Control: public, max-age=31536000 ← 1 年
VOD 推荐的缓存策略
| 文件类型 |
Cache-Control 推荐值 |
理由 |
| Manifest (.m3u8/.mpd) |
max-age=60 到 max-age=300 |
可能更新(如加广告、改字幕) |
| Init segment (.mp4) |
max-age=31536000(1 年) |
不变 |
| Media segment (.m4s/.ts) |
max-age=31536000(1 年) |
不变 |
| 字幕 (.vtt) |
max-age=3600(1 小时) |
可能修订 |
| 封面/缩略图 |
max-age=86400(1 天) |
可能更新 |
⚠️ 常见坑:如果切片 URL 里带签名参数(?token=xxx)没排除在缓存 key 外,每个用户的 URL 都是独立缓存条目,命中率直接为 0。详见本章 7.6。
7.5
请求合并(Request Collapsing)
假设 100 个用户同时请求 seg_42.m4s 且都 MISS:
没有合并:
100 个用户的 MISS 请求 → 100 个回源请求砸到源站 → 源站爆炸
有合并(现代 CDN 默认开启):
100 个用户请求 → Edge 认定是同一个对象 → 只发 1 个回源请求 → 响应后返回给 100 个用户
这叫 Request Collapsing / Coalescing。
大促开播、新剧首播时这是救命功能。
问题:CDN 上的切片 URL 是公开的,有人可能直接嵌入自己网站盗播。
解决方案:签名 URL / Token。
原理
视频分发前先签名,CDN 节点校验:
CDN 节点校验:
1. 是否过期?(看 Expires 参数)
2. 签名是否正确?(HMAC-SHA256 验证)
3. 参数未被篡改?
4. 可选:IP 绑定、UA 绑定
任何不符 → 返回 403 Forbidden
CloudFront 签名 URL 示例
https://d1234.cloudfront.net/video/seg_42.m4s
?Expires=1715084800
&Signature=nitfHRCrtziwO2HwPfWw~yYDhUF5EwRunQA-j19DzZrvDh6hQ73lDx~-ar3UocvvRQVw__
&Key-Pair-Id=APKAEIBAERJR2EXAMPLE
• Expires:过期时间戳(Unix)
• Signature:服务端用私钥签的
• Key-Pair-Id:对应的公钥 ID
后端签名代码(Python, 用 cryptography 库)
import time
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
import base64
def sign_url(resource_url, expires_in_sec, private_key_pem, key_pair_id):
expires = int(time.time()) + expires_in_sec
policy = f'{{"Statement":[{{"Resource":"{resource_url}","Condition":{{"DateLessThan":{{"AWS:EpochTime":{expires}}}}}}}'
private_key = serialization.load_pem_private_key(private_key_pem, password=None)
signature = private_key.sign(policy.encode(), padding.PKCS1v15(), hashes.SHA1())
signature_b64 = base64.b64encode(signature).decode()
.replace('+', '-')
.replace('=', '_')
.replace('/', '~')
return f"{resource_url}?Expires={expires}&Signature={signature_b64}&Key-Pair-Id={key_pair_id}"
让签名不影响缓存命中率
签名参数需要在 CDN 排除在 cache key 之外,或者由 Edge 计算:
常见做法:
Cache Key = URL path (不包含 query string)
or
Cache Key = URL path + 一些允许的白名单参数
签名参数 (Expires/Signature/Key-Pair-Id) 排除。
CloudFront、阿里云 CDN、Cloudflare 都有"基于 URL 签名但共享缓存"的配置。
其他防盗链手段
| 手段 |
作用 |
| Referer 白名单 |
只允许从特定域名引用 |
| UA 检查 |
过滤爬虫和非法 UA |
| IP 限制 |
按地域、国家屏蔽 |
| Rate Limit |
单 IP 请求频率限制 |
| 签名 Cookie |
HLS 加载多片段时比签名 URL 更方便 |
7.7
预热(Pre-warm / Pre-push)
新剧上架时,所有切片都不在边缘缓存里。第一波用户全 MISS → 体验差。
预热:CMS 发布后主动让 CDN 去源站拉一份到所有边缘节点。
CMS 发布钩子 → 调用 CDN 预热 API
├── POST /prewarm { urls: ["…/seg_0001.m4s", ..., "…/seg_0500.m4s"] }
└── CDN 调度所有边缘节点去回源
几分钟后:全球边缘节点都有了这批切片
第一波用户请求直接 HIT ✅
各家 CDN 预热 API
• AWS CloudFront:Invalidation 是失效,预热需要自己触发请求或用 AWS MediaPackage 的 prefetch
• 阿里云 CDN:PushObjectCache
• 腾讯云 CDN:PrefetchUrls
• Cloudflare:企业版 Prefetching
预热不是每个切片都预热,通常预热:
• Init segment
• 前 5-10 个切片(用户看头几秒最关键)
• 所有档位的上述切片
7.8
JIT Packaging vs Pre-packaging
两种打包策略:
Pre-packaging(离线打包)
转码完成 → 一次性生成所有 HLS/DASH/CMAF manifest 和 segment → 存 S3 → CDN 回源
优点:
• 简单,CDN 完全命中
• 延迟最低
缺点:
• 存储成本高(要存多套格式)
• 变更麻烦(加个字幕要重跑)
JIT Packaging(即时打包)
S3 只存 CMAF fMP4 源
用户请求 manifest → Origin 服务实时生成 → 返回 → CDN 缓存
优点:
• 存储只存一份
• 灵活(临时加 DRM、换字幕都容易)
缺点:
• 第一次命中稍慢(Origin 要 CPU 计算)
• Origin 服务要扛流量
代表实现:AWS MediaPackage-VOD、Unified Origin、开源 mp4box。
📌 推荐:
• 小库、高频访问内容:Pre-packaging
• 大库、长尾内容多、频繁变动:JIT Packaging
为什么一家 CDN 不够:
• 单点故障:CDN 挂了你全网挂
• 地域覆盖:没有一家 CDN 在全球每个地方都最好
• 议价能力:多家竞争你能拿到更好的价格
• 性能对比:实时选最快的那家
调度方式
方式 1:DNS 调度
video.example.com DNS 解析
├── 70% 请求 → CloudFront
├── 20% 请求 → Cloudflare
└── 10% 请求 → 阿里云
方式 2:客户端探测 + 中心调度服务
APP 启动时:
并发测试三家 CDN 的 TTFB 和丢包率
→ 选最快的那家
每 5 分钟重测一次
方式 3:专业调度服务
• Cedexis / Conviva Traffic Steering
• NS1、AWS Route 53 Latency-based Routing
• 自研调度中心
故障切换
播放器内置:
if (CDN A 连续失败 3 次):
切换到 CDN B
上报告警
7.10
HTTP 协议:HTTP/2、HTTP/3、QUIC 和视频
HTTP/1.1
• 默认协议
• 队头阻塞(HOL Blocking):一个 TCP 连接上一个请求慢,后面全部堵住
• 视频加载慢主要瓶颈之一
HTTP/2
• 多路复用(Multiplexing):一个 TCP 连接上并发多个请求
• 头部压缩、Server Push
• 视频场景受益明显(同时下多个切片)
HTTP/3 / QUIC
• 基于 UDP(不是 TCP)
• 消除 TCP 层队头阻塞(UDP 独立包)
• 0-RTT 建连(已访问过的站点瞬间连上)
• 弱网、高丢包场景性能大幅提升
📌 VOD / 直播启用 HTTP/3 后:移动网络、跨国、高丢包场景的起播时间和卡顿率会显著改善。主流 CDN(Cloudflare、CloudFront、阿里云)均已支持。
7.11
成本估算:一个 VOD 平台的 CDN 账单
常见带宽单价(Tier 3-4 折扣后参考)
| 区域 |
$/GB |
| 北美 / 欧洲 |
$0.005–$0.010 |
| 拉美 |
$0.020–$0.050 |
| 中东 |
$0.050–$0.080 |
| 亚太 / 印度 |
$0.015–$0.040 |
快速估算
假设:
DAU = 100 万
日均观看时长 = 30 分钟
平均码率 = 1.2 Mbps(720p H.264)
单用户日流量 = 1.2 Mbps × 1800s ÷ 8 ≈ 270 MB
DAU 日总流量 = 100 万 × 270 MB = 270 TB
月总流量 = 270 TB × 30 = 8.1 PB
按 $0.02/GB(加权平均):
月 CDN 成本 ≈ 8.1 PB × 1000 × $0.02 = $162,000
8 PB 算还好。同 DAU 但观看 60 分钟 + 1080p 3 Mbps,月成本翻 5 倍到 $81 万。
省钱手段
1. 编码优化:HEVC 比 H.264 省 37%、AV1 再省 20-30% → 直接减账单
2. Per-title encoding:为每部片子定制 ladder 省 10-20%
3. 下调默认档:手机默认 720p 比 1080p 省 40%
4. 多 CDN 竞价
5. CDN 阶梯折扣:月流量 > 1 PB 开始有大幅折扣
6. 私有 CDN:Netflix Open Connect 把服务器塞到 ISP 机房
🛠️ 动手试一试:用实际命令查看 CDN 缓存状态和节点信息。
查 CDN 命中情况
curl -I 'https://cdn.example.com/video/seg_42.m4s'
看响应头:
x-cache: HIT ← 命中(CloudFront、Cloudflare)
cf-cache-status: HIT ← Cloudflare 专用
age: 120 ← 缓存了 120 秒
或者 MISS 时:
查 CDN 节点
dig +short video.example.com
curl -I 'https://video.example.com/seg.m4s' | grep -i 'server\|via\|x-'
会看到类似 server: cloudfront、via: 1.1 abcd.cloudfront.net。
压测一下边缘命中率
用 ab 或 wrk 对同一个切片发 1000 请求,看命中率。第一个 MISS,后面应该全部 HIT。
✦ 本章要点回顾
1. CDN = 把内容缓存到离用户近的"便利店"。
2. 三层结构:Edge → Shield → Origin。
3. 缓存命中率 > 95% 是目标,签名参数一定要排除在 cache key 外。
4. 预热新剧避免第一波用户全 MISS。
5. JIT Packaging 省存储但要 Origin 扛;Pre-packaging 简单但费存储。
6. 多 CDN 提升稳定性、议价能力、地域覆盖。
7. HTTP/3 是弱网场景大礼包,尽快切。
8. VOD 带宽成本主导:编码效率 + 档位设置 + 多 CDN 竞价是三大杠杆。
© 2026 Zmead · VOD 流媒体技术全解