14、Probing与带宽探测:Probe机制、Padding包策略、探测结果处理、带宽估计更新

聊到WebRTC的拥塞控制,很多人会盯着BWE(带宽估计)的公式看半天。但说实话,真正让这套系统跑起来的,是Probing机制。没有它,你的带宽估计就像闭着眼睛开车——全靠猜。

我个人习惯把Probing比作「网络界的声呐探测」。你往网络里丢一些探测包,然后听回声,判断前方是坦途还是堵车。WebRTC的Probe机制,干的就是这个活。

14.1 Probe机制:为什么要主动探测?

先想一个问题:如果网络一直很稳定,带宽估计是不是就够用了?

不够。因为带宽估计本质上是「被动」的——它依赖实际发送的数据和接收到的反馈。如果当前应用层没有数据要发,或者发送速率远低于可用带宽,你就永远不知道网络到底能跑多快。

举个例子。我在项目中遇到过一种场景:用户从WiFi切换到4G,网络带宽从50Mbps掉到5Mbps。如果只靠被动估计,系统可能要花好几秒才能反应过来。这期间视频卡成PPT,用户早就骂娘了。

Probe机制就是为了解决这个问题。它主动发送探测包,试探网络的真实容量。说白了,就是「你不主动,我不主动,网络带宽永远是个谜」。

核心思想: 通过主动发送Padding包(填充包),在不影响实际媒体流的前提下,探测当前网络的可用带宽上限。

14.2 Padding包策略:怎么发?发多少?

Padding包,说白了就是「假数据」。它不携带任何有效载荷,纯粹为了占带宽。但怎么发、发多少,这里面门道很深。

WebRTC的Padding策略有几个关键点:

  • 时机选择: 只在发送队列空闲时发Padding。如果媒体数据排队等着发,Padding靠边站。优先级永远是:音频 > 视频 > FEC > Padding。
  • 速率控制: Padding的发送速率不能超过当前带宽估计值的1.25倍。我曾经见过一个实现,Padding发得太猛,直接把网络打爆了——嗯,那是个惨痛的教训。
  • 包大小: 通常使用MTU大小的包,或者接近MTU。小包Padding效率太低,浪费CPU。
  • 探测序列: 一次完整的探测通常包含多个「探测簇」(Probe Cluster)。每个簇是一组密集发送的Padding包,簇之间留出间隔等待反馈。
我的经验: 实际项目中,Padding包的发送频率不要超过每200ms一次。太频繁了,接收端处理不过来,反而影响RTT计算。

14.3 探测结果处理:从原始数据到带宽线索

探测包发出去之后,接收端会收到一堆反馈。这些反馈包括:

  • 每个包的到达时间
  • 包间延迟变化
  • 丢包率
  • 接收速率

但原始数据不能直接用。你需要做几件事:

  1. 过滤异常值: 网络抖动会导致个别包延迟异常。我习惯用中位数滤波,把Top 10%和Bottom 10%的数据扔掉。
  2. 计算探测带宽: 对于每个探测簇,用「总数据量 / 总传输时间」算出瞬时带宽。注意,这里的传输时间是从第一个包发出到最后一个包收到的时间差。
  3. 合并多个探测结果: 一次探测可能包含3-5个簇。取这些簇的中位数作为本次探测的「候选带宽」。
  4. 与当前BWE对比: 如果候选带宽比当前BWE高20%以上,说明网络有富余;如果低10%以上,说明网络可能变差了。
注意: 千万不要直接用单次探测结果更新BWE。网络是动态的,单次探测可能受突发流量影响。我建议至少连续两次探测结果一致,才触发BWE更新。

14.4 带宽估计更新:如何融合探测结果?

探测结果出来了,怎么用它更新带宽估计?这里有个经典的「信任与怀疑」的博弈。

WebRTC的带宽估计更新策略,我总结为三个原则:

场景 更新策略 说明
探测带宽 > 当前BWE 缓慢上调 使用指数加权移动平均(EWMA),权重0.2-0.3。避免一次探测就大幅上调。
探测带宽 < 当前BWE 快速下调 直接取探测带宽作为新BWE。网络变差时,反应要快。
探测带宽 ≈ 当前BWE 维持不变 说明当前估计是准确的,不需要调整。

你可能会问:为什么上调要慢,下调要快?

原因很简单:带宽高估的代价远大于低估。高估会导致网络拥塞、丢包、延迟飙升;低估最多就是视频分辨率低一点,但通话是流畅的。我在项目中吃过这个亏——有一次把上调权重设成了0.5,结果网络稍微好一点就猛提码率,然后瞬间拥塞,视频直接黑屏。

14.5 整体流程:一张图看懂

说了这么多,咱们用一张图把整个Probing流程串起来:

Probing带宽探测完整流程 触发探测条件 发送Padding探测簇 接收端反馈数据 过滤 & 计算候选带宽 更新带宽估计(BWE) 触发条件: • 发送队列空闲 • 距离上次探测 > 200ms • BWE未收敛 处理逻辑: • 中位数滤波 • 连续两次一致才更新 • 上调慢、下调快 持续循环探测

这张图把整个流程串起来了。从触发条件开始,到发送Padding、接收反馈、处理结果,最后更新BWE。注意那个循环箭头——Probing不是一次性的,它是持续进行的。网络环境在变,你的探测就不能停。

14.6 避坑指南:我踩过的几个坑

最后分享几个实战中容易踩的坑:

  • 坑一:Padding包和媒体包竞争带宽。 我曾经遇到过,Padding包发得太猛,把视频帧的发送延迟拉高了。解决方案:严格限制Padding的发送优先级,只在发送队列空闲时发。
  • 坑二:探测结果被噪声淹没。 在WiFi环境下,RTT抖动很大,单次探测结果可能偏差50%以上。我后来加了「连续两次一致才更新」的规则,效果好了很多。
  • 坑三:忘记处理探测超时。 如果探测包发出去后,接收端迟迟没有反馈(比如网络断开了),你的探测状态机要能超时回退。否则会一直卡在「等待反馈」状态,导致后续探测无法触发。
一句话总结: Probing是WebRTC拥塞控制的「眼睛」。没有它,你的带宽估计就是盲人摸象。但用好它,需要精细的策略和足够的容错机制。

好了,关于Probing和带宽探测,今天就聊到这里。下一章我们会深入GCC(Google Congestion Control)的算法细节,看看Google是怎么把拥塞控制做到极致的。


公众号:蓝海资料掘金营,微信deep3321