欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > 如何避免NACK重传风暴

如何避免NACK重传风暴

2025/2/9 10:30:10 来源:https://blog.csdn.net/ThinPikachu/article/details/145522437  浏览:    关键词:如何避免NACK重传风暴

策略 1,10 次

NACK 模块对同一包号的最大请求次数,超过这个最大次数限制,会把该包号移出 nack_list,放弃对该包的重传请求。

策略 2,20 毫秒

NACK 模块每隔 20 毫秒批量处理 nack_list,获取一批请求包号存储到 nack_batch,生成 nack 包并发送。

不过,nack_list 的处理周期并不是固定的 20ms ,而是基于 20ms 动态变化。

策略 3,100 毫秒

NACK 模块默认 rtt 时间,如果距离上次 nack 发送时间不到一个 rtt 时间,那么不会发送 nack 请求。

从发送 nack 请求到接收重传包一般是一个 rtt 的时间,也就是说重传包理论上应该在一个 rtt 时间内到来,超过这个时间还未到来,才会发送 nack 请求。

注意,100ms 只是 rtt 的默认值,在实际应用中,rtt 应该要根据网络状况动态计算,计算方式有很多种,比如对于接收端来说,可以通过发送 xr 包来计算 rtt。

策略 4,1000 个(丢失包数量)

nack_list 的最大长度,即本次发送的 nack 包至多可以对 1000 个丢失的包进行重传请求。

如果丢失的包数量超过 1000,会循环清空 nack_list 中关键帧之前的包,直到其长度小于 1000。也就是说,放弃对关键帧首包之前的包的重传请求,直接而快速的以关键帧首包之后的包号作为重传请求的开始。

策略 5,10000 个(包号跨度)

nack_list 中包号的距离不能超过 10000 个包号。即 nack_list 中的包号始终保持 [cur_seq_num - 10000, cur_seq_num] 这样的跨度,以保证 nack 请求列表中不会有太老旧的包号。

小结

策略 1 和策略 4 属于 nack 包发送的保护策略,这非常关键,比如有以下两种场景:

  • 场景 1,服务器下行分发链路丢包率过高。

这会导致接收端对一些包的重传请求次数过高,如果不对 nack 请求次数做限制,那么接收端将无限循环发送 nack 请求。

  • 场景 2,服务器上行推流链路出现长时间抖动,恢复后导致接收端 rtp 包号断层。

假如包号断层达到 1 万,那么在抖动恢复的瞬间,接收端会将 1 万个包号全部加入到 nack_list 。这会增加服务器生成 nack 包的负担,而且生成的 nack 包将达到 2.3KB 大小,推流端解析这个包同样也要耗费更多时间。

所以,如果没有 1、4 这两条 nack 保护策略,那么,当拉流用户很多的时候,上述两种场景会给服务器和端带来巨大的 cpu 性能损耗,并会引起 nack 网络风暴。不过,即使有这两条发送保护策略加持,有时还是会产生很多问题,比如下面这种场景。

  • 场景 3,上游服务器上行推流链路丢包,引发下游服务器回源分发链路丢包。

存在这种情况:上游服务器发送 nack 请求后,rtx 重传包还未到来,所以还未中继分发到下游服务器,然而此时下游服务已经收到了下游用户连续的并发的 nack 请求。针对这种场景,则需要对上行推流链路进行数据包排序,只有组成完整的帧才会中继分发到下游服务器,这样就避免了下游用户并发的 nack 请求。

其实,nack 的发送保护策略还有一条:收到一组连续且完整的帧之后,会立即对 nack_list 执行部分清空操作,避免无必要的再次重传请求,接下来的源码分析部分会进一步介绍这个策略。

最后,根据策略 1 和策略 3 的描述,我们可以推断出这样的结论:假设当前网络 rtt 为 100ms,那么 100ms * 10 次,恰好为 1s。也就是说,包在 1s 内还没有重传回来,那么就放弃它。

参考:WebRTC QoS | NACK 格式与发送策略-阿里云开发者社区

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com