14、Probing与带宽探测:Probe机制、Padding包策略、探测结果处理、带宽估计更新
聊到WebRTC的拥塞控制,很多人会盯着BWE(带宽估计)的公式看半天。但说实话,真正让这套系统跑起来的,是Probing机制。没有它,你的带宽估计就像闭着眼睛开车——全靠猜。
我个人习惯把Probing比作「网络界的声呐探测」。你往网络里丢一些探测包,然后听回声,判断前方是坦途还是堵车。WebRTC的Probe机制,干的就是这个活。
14.1 Probe机制:为什么要主动探测?
先想一个问题:如果网络一直很稳定,带宽估计是不是就够用了?
不够。因为带宽估计本质上是「被动」的——它依赖实际发送的数据和接收到的反馈。如果当前应用层没有数据要发,或者发送速率远低于可用带宽,你就永远不知道网络到底能跑多快。
举个例子。我在项目中遇到过一种场景:用户从WiFi切换到4G,网络带宽从50Mbps掉到5Mbps。如果只靠被动估计,系统可能要花好几秒才能反应过来。这期间视频卡成PPT,用户早就骂娘了。
Probe机制就是为了解决这个问题。它主动发送探测包,试探网络的真实容量。说白了,就是「你不主动,我不主动,网络带宽永远是个谜」。
14.2 Padding包策略:怎么发?发多少?
Padding包,说白了就是「假数据」。它不携带任何有效载荷,纯粹为了占带宽。但怎么发、发多少,这里面门道很深。
WebRTC的Padding策略有几个关键点:
- 时机选择: 只在发送队列空闲时发Padding。如果媒体数据排队等着发,Padding靠边站。优先级永远是:音频 > 视频 > FEC > Padding。
- 速率控制: Padding的发送速率不能超过当前带宽估计值的1.25倍。我曾经见过一个实现,Padding发得太猛,直接把网络打爆了——嗯,那是个惨痛的教训。
- 包大小: 通常使用MTU大小的包,或者接近MTU。小包Padding效率太低,浪费CPU。
- 探测序列: 一次完整的探测通常包含多个「探测簇」(Probe Cluster)。每个簇是一组密集发送的Padding包,簇之间留出间隔等待反馈。
14.3 探测结果处理:从原始数据到带宽线索
探测包发出去之后,接收端会收到一堆反馈。这些反馈包括:
- 每个包的到达时间
- 包间延迟变化
- 丢包率
- 接收速率
但原始数据不能直接用。你需要做几件事:
- 过滤异常值: 网络抖动会导致个别包延迟异常。我习惯用中位数滤波,把Top 10%和Bottom 10%的数据扔掉。
- 计算探测带宽: 对于每个探测簇,用「总数据量 / 总传输时间」算出瞬时带宽。注意,这里的传输时间是从第一个包发出到最后一个包收到的时间差。
- 合并多个探测结果: 一次探测可能包含3-5个簇。取这些簇的中位数作为本次探测的「候选带宽」。
- 与当前BWE对比: 如果候选带宽比当前BWE高20%以上,说明网络有富余;如果低10%以上,说明网络可能变差了。
14.4 带宽估计更新:如何融合探测结果?
探测结果出来了,怎么用它更新带宽估计?这里有个经典的「信任与怀疑」的博弈。
WebRTC的带宽估计更新策略,我总结为三个原则:
| 场景 | 更新策略 | 说明 |
|---|---|---|
| 探测带宽 > 当前BWE | 缓慢上调 | 使用指数加权移动平均(EWMA),权重0.2-0.3。避免一次探测就大幅上调。 |
| 探测带宽 < 当前BWE | 快速下调 | 直接取探测带宽作为新BWE。网络变差时,反应要快。 |
| 探测带宽 ≈ 当前BWE | 维持不变 | 说明当前估计是准确的,不需要调整。 |
你可能会问:为什么上调要慢,下调要快?
原因很简单:带宽高估的代价远大于低估。高估会导致网络拥塞、丢包、延迟飙升;低估最多就是视频分辨率低一点,但通话是流畅的。我在项目中吃过这个亏——有一次把上调权重设成了0.5,结果网络稍微好一点就猛提码率,然后瞬间拥塞,视频直接黑屏。
14.5 整体流程:一张图看懂
说了这么多,咱们用一张图把整个Probing流程串起来:
这张图把整个流程串起来了。从触发条件开始,到发送Padding、接收反馈、处理结果,最后更新BWE。注意那个循环箭头——Probing不是一次性的,它是持续进行的。网络环境在变,你的探测就不能停。
14.6 避坑指南:我踩过的几个坑
最后分享几个实战中容易踩的坑:
- 坑一:Padding包和媒体包竞争带宽。 我曾经遇到过,Padding包发得太猛,把视频帧的发送延迟拉高了。解决方案:严格限制Padding的发送优先级,只在发送队列空闲时发。
- 坑二:探测结果被噪声淹没。 在WiFi环境下,RTT抖动很大,单次探测结果可能偏差50%以上。我后来加了「连续两次一致才更新」的规则,效果好了很多。
- 坑三:忘记处理探测超时。 如果探测包发出去后,接收端迟迟没有反馈(比如网络断开了),你的探测状态机要能超时回退。否则会一直卡在「等待反馈」状态,导致后续探测无法触发。
好了,关于Probing和带宽探测,今天就聊到这里。下一章我们会深入GCC(Google Congestion Control)的算法细节,看看Google是怎么把拥塞控制做到极致的。