WebRTC 架构概览:P2P连接、信令、媒体流、数据通道
WebRTC 这玩意儿,说白了就是让浏览器之间能直接“对话”。不用经过服务器中转,视频、音频、文件,点对点就传过去了。听起来很酷,对吧?但实现起来,坑不少。
我刚开始接触 WebRTC 时,以为就是打开摄像头、塞进一个管道、另一端接收就完事了。结果呢?光是建立连接这一步,就折腾了我好几天。信令怎么设计?NAT 穿透怎么搞?媒体流怎么同步?数据通道丢包了怎么办?
嗯,这一章我们就来拆解一下 WebRTC 的整体架构。你搞懂了这些,后面调试流控、对抗抖动,才有根基。
2.1 核心架构:四个模块
WebRTC 的架构可以分成四个核心模块。我习惯把它们比作“四兄弟”:
- 信令(Signaling) —— 负责“牵线搭桥”,交换连接信息。
- P2P 连接(PeerConnection) —— 真正的数据传输通道。
- 媒体流(MediaStream) —— 摄像头、麦克风采集的音视频。
- 数据通道(DataChannel) —— 传输任意二进制数据。
这四兄弟缺一不可。信令是“媒人”,P2P 是“婚车”,媒体流是“新娘”,数据通道是“嫁妆”。你想想看,没有媒人,两个人怎么认识?没有婚车,新娘怎么到现场?
核心要点: 信令不是 WebRTC 协议的一部分,但它是建立连接的前提。你必须自己实现信令服务器。
2.2 信令:连接的“媒人”
信令的作用很简单:让两个浏览器知道对方的存在,并交换建立连接所需的信息。这些信息包括:
- SDP(Session Description Protocol) —— 描述媒体格式、编解码器、IP 地址、端口等。
- ICE Candidate(Interactive Connectivity Establishment) —— 候选的网络路径。
信令的流程大致是这样的:
- 发起方创建 Offer(SDP),通过信令服务器发送给接收方。
- 接收方收到 Offer,创建 Answer(SDP),再通过信令服务器发回去。
- 双方交换 ICE Candidate,尝试建立 P2P 连接。
我曾经在一个项目中,信令服务器用的是 WebSocket。一开始觉得挺简单,结果发现 SDP 里携带的 IP 地址是内网的,根本连不上。后来才意识到,需要配合 STUN/TURN 服务器做 NAT 穿透。
个人建议: 信令协议的设计要尽量轻量。别搞太复杂的 JSON 结构,否则解析起来费劲,还容易出错。我一般就用三个字段:type(offer/answer/candidate)、sdp、candidate。
2.3 P2P 连接:真正的“高速公路”
信令交换完成后,WebRTC 就开始尝试建立 P2P 连接。这个过程叫 ICE(Interactive Connectivity Establishment)。
ICE 会尝试多种路径:
- Host Candidate —— 本机 IP 地址,最快但只能在局域网内使用。
- Srflx Candidate —— 通过 STUN 服务器获取的公网 IP 地址。
- Relay Candidate —— 通过 TURN 服务器中转,最慢但最可靠。
ICE 会按照优先级排序,优先尝试 Host,不行再试 Srflx,最后才用 Relay。我遇到过不少情况,明明双方都在同一个局域网,ICE 却走了 Relay,延迟高得离谱。后来排查发现,是 STUN 服务器配置错了。
避坑指南: 我曾经在生产环境中忘记配置 TURN 服务器,结果用户在有对称 NAT 的网络环境下,死活连不上。那一次事故让我记住了:TURN 服务器不是可选项,是必选项。
下面这张图展示了 P2P 连接的建立过程:
2.4 媒体流:音视频的“血液”
P2P 连接建立后,媒体流就开始传输了。媒体流包括视频轨道(VideoTrack)和音频轨道(AudioTrack)。
WebRTC 使用 getUserMedia() 获取本地媒体流,然后通过 addTrack() 添加到 PeerConnection 中。接收方通过 ontrack 事件获取远程媒体流。
这里有个关键点:媒体流的编码和解码。WebRTC 默认使用 VP8/VP9 视频编码和 Opus 音频编码。但不同的浏览器支持的编码器不一样。我遇到过 Chrome 和 Safari 之间视频通话,Safari 不支持 VP9,结果 Chrome 只能降级到 VP8,画质差了不少。
个人经验: 在建立连接前,最好先协商一下双方都支持的编解码器。可以通过 SDP 的 rtpmap 字段来查看。我一般会优先使用 H.264,因为硬件编码支持更好,延迟更低。
2.5 数据通道:传输“任意数据”
数据通道(DataChannel)是 WebRTC 里一个容易被忽视但非常强大的功能。它可以在 P2P 连接上传输任意二进制数据,比如文件、游戏状态、聊天消息等。
数据通道有两种模式:
| 模式 | 特点 | 适用场景 |
|---|---|---|
| 可靠模式 | 基于 SCTP 协议,保证数据有序、不丢失 | 文件传输、聊天消息 |
| 不可靠模式 | 基于 SCTP 协议,允许丢包和乱序 | 实时游戏状态、音视频同步 |
我曾在做一个在线协作白板项目时,用数据通道传输画笔轨迹。一开始用的可靠模式,结果网络一抖,白板就卡住了。后来改成不可靠模式,丢几个点无所谓,用户体验反而更流畅。
避坑指南: 数据通道的 maxRetransmits 和 maxPacketLifeTime 参数不能同时设置。我曾经踩过这个坑,两个都设了,结果数据通道创建失败。记住:要么设置重传次数,要么设置生存时间,二选一。
2.6 架构总结:一张图看懂
好了,我们把整个 WebRTC 架构串起来。下面这张图展示了各模块之间的关系:
你看,从应用层到网络层,每一层都有明确的职责。信令负责“牵线”,P2P 负责“修路”,媒体流和数据通道负责“跑车”。搞懂了这些,你就能理解为什么网络抖动会影响视频质量,为什么 ICE 连接会失败,为什么数据通道会丢包。