上一篇我们用「延迟、主权、成本」三本账说清了为什么值得自建。这一篇把架构图摊开:一套自建低延迟直播 CDN 到底由哪些部分组成,媒体数据从推流端怎么走到观众端,以及为什么几乎所有的「高可用」结论,都建立在一条最基础的设计原则之上------**控制面与媒体面彻底分开**。
一、一张图看全貌:三层媒体链路 + 一个控制面
一套典型的自建低延迟直播系统,媒体链路本质上只有三层,外加一个「画在链路上方、却不在数据路径上」的控制面:
```
控制面
调度 · 鉴权 · 信令 · 计费元数据 · 健康报告
▲ ▲
│ 控制 / 信令 │ 控制 / 信令
│ │
推流端 ──WHIP/SRT──▶ Origin ──转发──▶ Edge 1..N ──WHEP──▶ 观众浏览器
│ ▲
└──────────── P2P 直连(可选捷径,失败顺序回退 Edge)─────┘
```
-
**推流端**:可以是自研/定制的推流客户端,也可以是任意标准的 WHIP / SRT 推流端。
-
**Origin(源站)**:接收推流的源站,是媒体数据进入系统的唯一入口。
-
**Edge(边缘,可多台)**:从 Origin 回源,向观众分发。同一路流在同一台 Edge 上被多个观众共享一条回源链路。
-
**控制面**:负责调度、鉴权、节点管理、P2P 信令、计费元数据和健康报告,**不承载媒体数据、不代理媒体包**。
链路两端都是标准 WebRTC 的话,媒体经 DTLS-SRTP 加密。整套系统可以自建、可以托管,节点掌握在自己手里。
二、为什么控制面和媒体面必须分开
这是整套架构里最基础的一条原则,值得单独讲。
如果调度、鉴权这些「决策逻辑」和音视频数据混在同一条链路里,控制面抖一下,正在观看的观众就跟着抖。分开之后,媒体包完全不经过控制面:**控制面主要参与连接建立、鉴权和调度,连接一旦建立,媒体走独立链路,控制面故障不会中断正在进行的观看。**
这条原则带来一个很实际的后果:故障域被彻底缩小了。控制面挂了,你损失的是「新的连接建立不了」,而不是「正在看的观众全掉线」。控制面恢复后,各端重新注册、重建租约即可。
对一个「直播正在赚钱」的业务来说,这两者的区别就是「暂时接不了新客」和「营业额直接归零」的区别。
三、时钟同步:跨端时间戳有意义的前提
低延迟系统里还有一条容易被忽略的隐形地基:**时钟同步**。
短期凭证的有效期判定、跨端延迟埋点、故障判定,全都依赖时间。如果推流端和播放端的时钟各走各的,那么「采集时间」和「渲染时间」相减得出的数字就毫无意义,甚至可能算出负延迟。
所以自建方案通常会:
-
让各端通过 NTP 之类的机制同步时钟,并监控偏差;
-
以控制面为**公共参照**,让全网时钟「自洽」------目标不是绝对 UTC 精确到微秒,而是让不同节点的时钟彼此可比;
-
在鉴权上允许明确、有限的 clock-skew 容差。
这一点会在讲「如何量出端到端延迟」时详细展开。这里先记住结论:**没有可信的时钟,就没有可信的延迟数字。**
四、节点角色化:同一套媒体内核,不同部署形态
一个实用的工程做法是:Origin、Edge、Recorder(录像)、Forward(跨区域桥接)等角色,往往由**同一份媒体服务代码按配置角色化**,而不是四套完全不同的程序。
这样做的好处很直接:
-
协议栈、运维方式、监控口径统一;
-
扩展边缘只是「多起几个角色为 Edge 的实例」;
-
新增角色(比如录像)可以复用已有的注册、心跳、容量上报机制。
需要区分的两个概念是:**控制面「知道」某台节点在线**,和**控制面能自动把任务调度给它**,是两件不同的事。前者靠注册与心跳,后者还要求有完整的选点、租约和故障重试逻辑。很多系统停在前者,却把它当成后者来宣传,这是接入时要留意的边界。
五、媒体数据怎么走:一条主链路 + 一条可选捷径
把角色展开,媒体面大致是这样连起来的:
```
推流端 ──WHIP/SRT──▶ Origin ──转发──▶ Edge ×N ──WHEP──▶ 播放端
│ ▲
└──────────── P2P WebRTC 直连(可选,绕开 Origin/Edge)───┘
```
三个关键点:
-
**Origin 是稳定收流的核心入口。** 某一路流通常只进一个 Origin,它负责稳定接收推流、为下游提供回源。
-
**Edge 是被动接收 Origin 推流的。** Origin 反过来充当推流客户端,把流推给 Edge。这个机制天然支持「一条路径推给任意多个目标」,跨区域桥接也建立在这个与区域无关的推送机制之上,而不是靠代码里判断「我在哪个云区域」。
-
**P2P 直连是一条捷径。** 观众与推流端 NAT 穿透成功后,媒体直接从推流端流向观众,绕开 Origin/Edge,既不占边缘出口带宽,也是理论上延迟最低的路径。它用推流端的富余上行换取成本下降,但**永远是可选项**------连不上就干净回落到 Edge。
六、播放选路:按能力分流,失败顺序回退
「低延迟」不是靠一条路径硬扛,而是靠一套清晰的选路决策。一个常见且稳健的做法是**按播放端解码能力分流 + 顺序回退**:
```
观众发起播放请求
│
▼
探测播放端能否硬解 HEVC
│
├─ 支持 HEVC ──▶ 直接走 Edge 的 HEVC 流
│
└─ 不支持 HEVC
│
▼
优先尝试 P2P 直连拉 H264
│
├─ 准入通过 + 有空闲名额 ──▶ 中继信令建立直连 ──▶ 走 P2P
│
└─ 准入未过 / 超时 / 建连失败 / 名额已满 ──▶ 干净回落到 Edge
```
这里有三个值得说明的设计选择:
-
**「按能力分流」而不是「无脑竞速」。** 早期一些实现让 P2P 和 Edge 并行抢首帧(谁先出画面用谁),这会让建连过程复杂、首帧时间不可预测。更清晰的模型是:HEVC 客户端直接走 Edge(同画质下更省流量,也避开 P2P 建连的首帧不确定性);H264 客户端才尝试 P2P,且**在同一个决策响应里就带好 Edge 兜底地址**,不需要二次请求。
-
**「顺序回退」保证兜底永远可用。** 任一环节没通过、超时或失败,都不报错、不黑屏,直接改用已经拿在手里的 Edge 地址。
-
**P2P 只用富余上行。** 主推流的画质和带宽预算是第一优先级,一旦检测到上行拥塞,立刻牺牲 P2P,主推流不受影响。
这套「按能力选路 + P2P 优先、失败回退」的模型,会在后面讲 P2P 和扩容时反复出现。
七、Edge 自治:控制面抖动,媒体面不跟着抖
控制面与媒体面分离有一个具体落点:**Edge 的自治能力**。
Edge 每次回源前向控制面动态解析 Origin 地址和短期媒体凭据,并把解析结果缓存在内存里。控制中心不可用时,Edge 可以复用未过期的缓存继续重连------**只要缓存的凭据还没过期、源站还活着,控制面这段时间在不在线,观众体感上可能完全无感。**
需要诚实地划清边界:这解决的是「控制面短暂故障」和「网络闪断」,**不是「源站真的挂了」**。如果 Origin 节点本身故障,推流端需要重新发布到一个新的源站,这段切换会有可感知的中断。把这类情况包装成「什么故障都能无缝恢复」是不诚实的。
小结
-
**三层媒体链路 + 一个控制面**:推流端 → Origin → Edge → 观众,控制面只做决策和信令,不碰媒体。
-
**控制面与媒体面分离**是最基础的设计,它把故障域做小,让控制面故障不中断正在进行的观看。
-
**时钟同步**是跨端延迟埋点的前提,没有可信时钟就没有可信延迟。
-
**节点角色化**让 Origin / Edge / Recorder / Forward 共享同一套媒体内核,便于扩展。
-
**播放选路**按解码能力分流,P2P 优先、失败顺序回退 Edge,兜底永远可用。
-
**Edge 自治**保证控制面抖动不波及媒体面,但不等于源站故障也能无缝切换。
下一篇,我们回到最基础的传输层:RTMP、SRT、WHIP 这三种协议到底该怎么选,以及「多档画质」是怎么在不做服务端转码的情况下实现的。
**系列导航**
- 下一篇:03 · 传输协议与多档画质(03-传输协议与多档画质-RTMP-SRT-WHIP与Simulcast.md)