第 7 章 · CDN 分发:为什么全球打开都很快

VOD 流媒体技术全解 · 第 7 章(共 12 章)· 预计阅读 20 分钟

本章你会理解:CDN 是什么、为什么视频必须上 CDN、边缘/中转/源站三层结构、签名防盗链、多 CDN 调度、以及一个 VOD 平台的 CDN 账单大概长什么样。

• • •
7.1

为什么必须上 CDN

假设你在上海搭了一台服务器放视频,美国用户来看:

美国用户 ────🌊 跨太平洋海底光缆 🌊────► 上海服务器
                  (延迟 180ms+)
                  (丢包率高)
                  (带宽受限)

每个美国用户每秒从你的上海服务器拉 2 Mbps 视频,10 万美国并发用户 = 200 Gbps 跨国出口。这在技术和成本上都不可能。

CDN(Content Delivery Network,内容分发网络) 解决方案:

              ┌─── 美国纽约缓存节点 ───► 美国用户(延迟 20ms)
上海源站 ────►
              └─── 法兰克福缓存节点 ───► 欧洲用户(延迟 10ms)

第一次回源后,热门视频就"驻扎"在全球节点里

💡 类比:CDN 像全球连锁便利店。总部在一个地方生产商品(源站),但分销到每个城市的便利店(边缘节点)。用户就近购买,既便宜又快。

• • •
7.2

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%

• • •
7.3

回源(Origin Pull)过程

用户请求一个切片的完整流程:

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

大促开播、新剧首播时这是救命功能。

• • •
7.6

防盗链:签名 URL / Token

问题: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

• • •
7.9

多 CDN 策略

为什么一家 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 机房

• • •
7.12

动手:测一下一个视频的 CDN 表现

🛠️ 动手试一试:用实际命令查看 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 时:

x-cache: MISS

查 CDN 节点

dig +short video.example.com
curl -I 'https://video.example.com/seg.m4s' | grep -i 'server\|via\|x-'

会看到类似 server: cloudfrontvia: 1.1 abcd.cloudfront.net

压测一下边缘命中率

abwrk 对同一个切片发 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 流媒体技术全解