一、千人会议的 QoS 挑战:从 10 人到 1000 人的质变

说实话,我第一次接到「千人会议」的需求时,心里是有点发怵的。做 WebRTC 的人都知道,10 个人的会议和 1000 个人的会议,根本不是一个物种。

10 个人的时候,每个人发一路视频,接收端也就 9 路。带宽不够?降分辨率、降帧率,甚至直接关掉几路,问题不大。但到了 1000 人,每个人发一路,接收端理论上要处理 999 路。你想想看,就算每路只有 500kbps,总带宽也接近 500Mbps。这还不算 CPU、内存、编解码的开销。

我在项目中遇到过最夸张的情况:一个 800 人的全员大会,某位领导的网络突然抖动,结果整个房间的接收端都开始卡顿。为什么?因为 SFU 没有做合理的带宽分配,一个用户的波动拖累了所有人。

所以,大规模场景下的 QoS,核心挑战就三个:

  • 带宽瓶颈:上行、下行、服务器出口,处处是瓶颈
  • 计算压力:编解码、转码、混流,CPU 和 GPU 扛不住
  • 网络异构:有人用 5G,有人用 Wi-Fi,有人还在用 3G

说白了,你要在「有限的资源」和「无限的参与者」之间找到平衡点。

二、带宽分配策略:谁该吃蛋糕,谁该喝粥?

带宽分配,我个人的习惯是「按需分配,动态调整」。你不能给所有人一样的带宽,那是对资源的浪费。

2.1 基于活跃度的带宽分配

一个 1000 人的会议,真正在说话的可能只有 3-5 个人。其他人要么在听,要么在摸鱼。这时候,你应该把大部分带宽给活跃用户。

具体怎么做?

  • 活跃用户:分配高清视频(720p/1080p),音频优先
  • 非活跃用户:只传音频,或者传低分辨率视频(180p/360p)
  • 静默用户:只传音频,甚至音频也可以降采样

我曾经在一个项目中,把非活跃用户的视频分辨率降到 180p,帧率降到 5fps。结果呢?服务器带宽直接降了 60%,用户感知几乎没有变化。因为没人会盯着一个不说话的人看。

2.2 基于网络质量的带宽分配

嗯,这里要注意:不是所有用户都有资格吃高清蛋糕。网络差的用户,你给他 1080p 他也收不到,反而会卡死。

我建议的做法是:

  1. 接收端定期上报网络状态(RTT、丢包率、可用带宽)
  2. SFU 根据上报数据,动态调整发送码率
  3. 如果丢包率超过 5%,自动降一档分辨率
  4. 如果 RTT 超过 300ms,降低帧率

说白了,就是「看人下菜碟」。网络好的吃高清,网络差的喝粥,但至少保证能喝上。

2.3 公平性 vs 效率

这里有个经典矛盾:公平性和效率怎么平衡?

如果完全公平,每个人分 1Mbps,那 1000 个人就需要 1Gbps 的服务器带宽。现实中不可能。如果完全效率优先,那网络差的人可能永远看不到视频。

我的经验是:保证底线,上不封顶。每个人至少保证音频流畅(约 50kbps),视频最低 180p(约 200kbps)。剩下的带宽,按活跃度和网络质量动态分配。

三、层级化 QoS 设计:从端到端的全链路保障

层级化 QoS,说白了就是把问题拆成三层:应用层、传输层、网络层。每一层解决不同的问题。

核心思想:不要试图在一个层面解决所有问题。应用层管策略,传输层管可靠性,网络层管优先级。

3.1 应用层 QoS

应用层离用户最近,也最灵活。我在这里主要做三件事:

  • 码率自适应:根据网络状况动态调整编码参数
  • 流优先级:音频 > 视频 > 屏幕共享 > 文件传输
  • 丢包重传策略:关键帧(I帧)必须重传,非关键帧(P帧)可以跳过

举个例子:当网络拥塞时,我会优先保证音频的码率,然后压缩视频码率。如果还不够,就降低非活跃用户的视频分辨率。最后才考虑丢帧。

3.2 传输层 QoS

传输层主要靠 WebRTC 自带的机制:

  • FEC(前向纠错):发送冗余包,允许一定比例的丢包恢复
  • NACK(否定确认):接收端通知发送端重传丢失的包
  • Jitter Buffer(抖动缓冲):平滑网络抖动,保证播放流畅

我记得有一次线上事故,某个区域的用户丢包率高达 20%。FEC 扛不住,NACK 也来不及。最后怎么解决的?我们把 FEC 的冗余度从 10% 提升到 30%,同时把 Jitter Buffer 从 100ms 增加到 300ms。虽然延迟变大了,但至少画面不卡了。

避坑指南:我曾经把 FEC 冗余度设得过高(50%),结果带宽消耗翻倍,反而加剧了拥塞。FEC 不是越高越好,要根据实际丢包率动态调整。

3.3 网络层 QoS

网络层是最底层的保障,也是最难控制的。因为你管不了用户的网络,只能管自己的服务器。

我常用的手段:

  • DSCP 标记:给音频包打高优先级标记(EF),视频包打中优先级(AF),其他包打低优先级(BE)
  • 带宽预留:在服务器出口预留 20% 的带宽给音频和关键信令
  • 多路径传输:如果用户有多个网络接口(Wi-Fi + 4G),可以同时使用,提高可靠性

但说实话,DSCP 标记在公网上不一定生效,因为很多运营商会忽略它。所以,我更推荐在私有网络或专线中使用。

四、层级化 QoS 架构图

下面这张图是我自己总结的层级化 QoS 架构,你可以把它当作设计参考:

层级化 QoS 设计架构 应用层 QoS 码率自适应 | 流优先级(音频 > 视频 > 屏幕共享) | 丢包重传策略 关键帧(I帧)必须重传,非关键帧(P帧)可跳过 传输层 QoS FEC(前向纠错) | NACK(否定确认) | Jitter Buffer(抖动缓冲) FEC 冗余度动态调整(10%~30%),Jitter Buffer 100ms~300ms 网络层 QoS DSCP 标记(音频 EF,视频 AF,其他 BE) | 带宽预留(20%) | 多路径传输 注意:DSCP 在公网可能被忽略,建议在私有网络中使用 三层协同工作,从策略到可靠性再到优先级,全链路保障 QoS

五、实战中的避坑指南

最后,分享几个我踩过的坑,希望能帮你少走弯路。

坑1:不要迷信 FEC

我曾经在一个项目中,把 FEC 冗余度设到 50%,以为能扛住 30% 的丢包。结果带宽翻倍,拥塞更严重,丢包率反而上升了。后来我改成动态 FEC:丢包率低时用 10%,丢包率高时用 30%,超过 30% 就放弃 FEC,改用 NACK + 降分辨率。

坑2:不要忽略音频优先级

有一次线上会议,视频卡得不行,但音频是好的。用户反馈说「虽然画面不动,但至少能听清」。这说明音频优先级策略生效了。反过来,如果音频也卡,那用户就彻底没法用了。所以,任何时候都要保证音频的带宽和优先级。

坑3:不要假设所有用户网络都很好

我见过最极端的案例:一个用户用 2G 网络参加 1080p 会议。结果他一个人占用了 SFU 的大量资源,还拖累了其他用户。后来我们加了一个「最低网络要求」的检测:如果带宽低于 500kbps,强制降为音频-only。虽然用户不爽,但至少不影响其他人。

六、总结

千人会议的 QoS,说白了就是「在有限的资源下,让尽可能多的人获得可用的体验」。没有银弹,只有权衡。

我个人的经验是:分层设计,动态调整,保证底线。应用层管策略,传输层管可靠性,网络层管优先级。三层协同,才能在大规模场景下稳住阵脚。

嗯,今天就聊到这里。如果你在实际项目中遇到什么问题,欢迎随时交流。


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