7.2 抗丢包技术 NACK 与 FEC 带宽预算再准,也挡不住包在路上丢。本节讲引擎的武器库:重传怎么追回单包、冗余怎么顶住随机丢、关键帧怎么兜底大损失,以及三件武器的带宽代价与调度逻辑。弱网优化的核心功夫,全在这套"按丢法选武器"的判断里。 武器一:重传,精确制导的追补 接收方发现序号缺口后,向发送方点名请求补发,这就是否定确认重传。它的优点是精确——丢什么补什么,不浪费字节;代价是时间——一个来回的线路延迟。因此重传的适用边界由 RTT 决定:线路快(RTT 几十毫秒)时,补包赶得上播放节奏,重传近乎无损;线路慢时,补包到了也迟了,白花带宽。引擎据此设定重传的生效窗口,并对每个序号限制重传次数,防止对永久丢失的序号反复请求。
带宽预算再准,也挡不住包在路上丢。本节讲引擎的武器库:重传怎么追回单包、冗余怎么顶住随机丢、关键帧怎么兜底大损失,以及三件武器的带宽代价与调度逻辑。弱网优化的核心功夫,全在这套"按丢法选武器"的判断里。
接收方发现序号缺口后,向发送方点名请求补发,这就是否定确认重传。它的优点是精确——丢什么补什么,不浪费字节;代价是时间——一个来回的线路延迟。因此重传的适用边界由 RTT 决定:线路快(RTT 几十毫秒)时,补包赶得上播放节奏,重传近乎无损;线路慢时,补包到了也迟了,白花带宽。引擎据此设定重传的生效窗口,并对每个序号限制重传次数,防止对永久丢失的序号反复请求。
重传包走独立的流——不同的同步源标识、可追溯的计数——这带来两个工程便利:接收端统计"重传救回了多少"有精确口径;转发服务器可以按需丢弃重传流而不伤主流。排错时看这条流的速率变化,能直接读出线路的丢包强度。
前向纠错的思路相反:不等丢,先备胎。发送端按一定比例把若干个包的数学组合作为冗余包一并发出,接收端只要到手的是"原包加冗余包"中的任意多数,就能把丢掉的那个算回来。它不怕 RTT——恢复零往返——但带宽代价刚性:两成冗余就是两成的固定开销,线路好的时候纯纯浪费。
所以冗余的正确形态是动态的:引擎按丢包率与冗余recover率的权衡曲线,实时调整冗余度——丢包抬头,冗余跟上;线路恢复,冗余撤防。视频侧还要考虑码率分蛋糕的约束:冗余开销与画质开销共享预算,带宽越紧,两者越要精打细算,这个分配在 7.3 的机制里完成。音频侧另有一件特殊武器:编码器内置的帧内冗余——把上一帧的低码率版本嵌进当前帧,开销比例更优,4.2 节讲的弱网联动就是它在工作。
丢到参考帧、依赖链断裂时,前两件武器都救不了——那就请发送方重新发一个关键帧,接收方从它重新出发。关键帧的代价最高:体积是普通帧的几倍到几十倍,还会造成码率尖峰。因此引擎对关键帧请求有节流纪律:请求有最小间隔,接收方不会因连环丢失而狂发请求把线路打死。看统计里的关键帧请求计数可以读出很多信息:偶发几个是正常损耗,持续高企说明丢包严重到依赖链频繁断裂,线路质量已经很差。
| 武器 | 时间代价 | 带宽代价 | 最擅长 | 最忌讳 |
|---|---|---|---|---|
| 重传 | 一个 RTT | 只补所缺 | 高丢包加低延迟 | 高延迟线路 |
| 动态冗余 | 零 | 按冗余度固定 | 随机散丢加任何延迟 | 突发连片丢 |
| 关键帧 | 请求加解码 | 尖峰式 | 依赖链断裂兜底 | 频繁触发 |
三件武器的搭配由丢法决定:随机散丢用冗余最划算;单点缺失且线路快用重传最省;突发连片丢是两者共同的克星——冗余包常常与正主一起丢,重传要追一长串——此时交错打包把连续丢"打散"成散丢,能救回武器的效率。
三件武器的调度由一组参数驱动,把常用项与工程含义收拢成表,弱网策略调优时按表索骥。
| 参数项 | 工程含义 | 调整方向 |
|---|---|---|
| 重传窗口 | 缺口追补的时间范围 | 与 RTT 匹配,勿超播放余量 |
| 单序号重传上限 | 对永久丢失的止损 | 调低省带宽、调高追回率 |
| 冗余介入阈值 | 冗余开启的丢包点 | 延迟敏感场景提前 |
| 冗余撤防阈值 | 冗余关闭的丢包点 | 与介入阈值留出滞回带 |
| 关键帧请求间隔 | 兜底武器的节流 | 调小恢复快、带宽伤重 |
表里"滞回带"一词值得展开:介入与撤防若是同一个点,丢包率在阈值附近徘徊时冗余会反复开关,带宽随之锯齿震荡。留出一段差距——比如百分之三介入、百分之一撤防——武器状态就稳定得多。这种滞回思想在引擎的许多开关型决策里反复出现,是抗震荡的通用手法,读其他模块时可以举一反三。
最后补一句武器调度与 7.3 分配器的接口关系,把闭环说圆。武器的开销不是自变量而是分配的从变量:冗余额度在分配器的账本上占一行,随预算与丢包动态伸缩;重传流量从被补流的份额内扣账;关键帧作为尖峰事件走紧急通道,但事后要在该流的份额里"还债"(短暂压低后续发送)。这套记账设计让武器永远不能超发——弱网下所有手段的消耗都被约束在总预算内,不会出现"抗丢包把自己挤垮"的死循环。理解了这层接口,再看 7.3 的分配表,你会明白那不只是画质分配,也是整场弱网作战的军费预算。
背景。弱网演练要求量化回答一个问题:丢包一成的线路上,只开重传与重传加动态冗余,体验差多少、带宽各花多少。演练结果要写进产品的弱网策略文档。
操作。固定线路模拟器的丢包率为随机模型一成,跑两组各五分钟的通话。第一组只开重传:统计显示重传流活跃,救回率约九成,但播放端延迟被缓冲自动抬高约一百毫秒——重传的往返在缓冲里被消化;画面偶发等待。第二组开重传加动态冗余:冗余稳定在两成上下,救回率九成八,缓冲增量只有三十毫秒,画面等待基本消失;总带宽开销比第一组高约一成五。
结果。结论写入策略文档:丢包率一成以下优先重传,延迟敏感场景冗余随丢包率动态介入,阈值定在百分之三介入、百分之一撤防,与 4.2 的弱网联动参数对齐。
解读。两组数据的对比揭示了武器选择的本质——在延迟与带宽之间买保险:重传用延迟换带宽,冗余用带宽换延迟。没有普适的正确答案,只有场景化的合理区间。演练的另一收获是突发模型下的数据:同样的平均丢包率换成突发模型,重传救回率跌到七成、缓冲抬升翻倍——突发丢是重传的天敌,这直接催生了"交错打包"在弱网策略中的保留位。
变式。把演练的线路延迟从五十毫秒拉到两百毫秒再跑,重传的价值崩塌——补包赶到时播放时刻已过——而冗余表现几乎不变。这组对照常被用来回答"跨洋线路要不要开冗余":延迟越大,冗余越不可替代。同一套演练框架,换参数就能回答任何弱网策略问题,建议每个团队都把它建成常设实验。
本节要点:重传精确但吃 RTT,冗余零往返但吃带宽,关键帧兜底但最贵;冗余必须动态化,静态配置要么浪费要么失效;突发丢是重传与冗余共同的克星,交错打包是解药;武器配置的本质是延迟与带宽之间的保险购买决策,场景化演练是唯一的定价依据。下一节回到预算的终点:多路并存时,这块蛋糕到底怎么切。