网易云信线上万人连麦技术大揭秘

语言: CN / TW / HK

首图.jpg

技术系列课回顾 | 网易云信线上万人连麦技术大揭秘

本文根据网易云信资深音视频服务端开发工程师陈策在《MCtalk Live#5:网易云信线上万人连麦技术大揭秘》线上直播分享整理。

导读

大家好,我是来自网易云信的陈策。连麦作为一个强互动场景,单房间内的高并发一直是个比较复杂的问题。这次给大家分享网易云信在万人连麦这个场景上的探索和实践。

比较典型的万人连麦需求场景有视频会议研讨会、低延迟直播、在线教育大班课、类 Club House(多人语聊房)等。对于万人连麦的需求场景市面上普遍的解决方案是“RTC+CDN”的方式,即限制上麦主播人数在小规模(50人左右)进行 RTC 互动,然后转推到 CDN,大规模的观众再通过 CDN 直播拉流的方式实现。这种解决方案在业务上限制了上麦人数,并且观众和主播之间有较大的声画延迟,无法满足云信的业务要求。例如,在游戏语音场景中,会有大量的用户开公麦,需要做到所有人都可以上麦,并且上麦人数不限制。那么,网易云信是如何解决这个问题的呢,本文将和大家分享我们在这个问题上的探索。

信令的技术难点

信令并发、弱网和高可用问题

我们在这个问题的探讨分为几个方面:信令、音频技术、视频技术以及服务器间的网络传输,先来看看信令的实现。

RTC 是使用长连接进行双向通知的。假设某个语聊房主播有一万人,那么只要其中某一个主播上/下麦或者加入/离开房间,都会触发对其它 9999 人的信令通知。这种随机的用户行为会让服务器瞬时压力非常大。

传统的中心化单点服务器显然是支撑不了万人房间这么大并发的,必须使用分布式架构来分散压力。假如一个万人房间分布在多台服务器上,那么服务器之间还要实时同步 Nx(N-1) 的用户状态和发布订阅关系,同时为了实现高可用,还需要支持某台服务器崩溃重启后的数据同步。

另一方面,媒体服务器一般会做成分布式网状架构来降低点对点的延迟。但如果信令服务器也保持每一个节点都平等的网状架构,那么每一个节点都要维护全量的级联关系。这其中错综复杂的消息同步性问题将会极难维护。

网易云信分布式树状架构

为了实现高并发和高可用,结合信令都是在房间内部传递,房间之间不会有信令交互这一业务特点,我们将信令服务器设计成分布式树状架构,每个房间是一颗独立的树,如下图:

  • 根节点:房间管理服务器,管理和存储所有的用户状态和订阅关系。
  • 子节点:作为边缘服务器,负责用户就近接入。

这种树状架构可以有效分散各节点的广播压力。根节点会尽量根据就近用户的原则进行分配,避免其与子节点之间链路过长,同时子节点尽量只充当消息 proxy,不参与业务,把业务集中到根节点上,从而避免信令的同步乱序等问题。

根节点使用缓存加数据库来保证业务数据存储的性能和可靠性。子节点由于不涉及用户业务状态,在崩溃重启后,只需要客户端信令的长连接重连,不用进行类似重新加入房间的操作,做到对用户无感知。在遇到子节点宕机的情况下,则会依靠客户端的超时机制,重新请求调度。通过这一系列手段,实现服务的高可用。

信令弱网问题

在RTC架构中,由于信令非常多且交互复杂,一般采用信令和媒体通道分离的策略。但这会引入一个问题,就是两者的抗弱网能力不一致。媒体一般使用Udp传输,很容易做到在30%丢包下依然能流畅观看。但信令一般使用Tcp传输,30%丢包下信令就基本不可用了。

为了解决这个问题,我们使用Quic作为信令加速通道,来保证信令媒体的弱网对抗能力一致性。同时在Quic连不通时(可能存在用户网络对某些Udp端口不友好),也能退避到Websocket,以此来保证信令在弱网下的高可用。

音频的技术难点

混音和选路的缺陷

在多人连麦场景中,最复杂的就是多个用户同时说话场景下的音频并发问题。

假设万人房间中每个主播都上麦,由于语音的特性,每个主播理论上都要订阅其它所有人(视频可以按需订阅,但音频理论上应该全订阅)。如果每个客户端都订阅 N-1(9999) 路流,不仅仅是流量的浪费,客户端也支持不了如此多的下行,而且在现实场景中,只要超过 3 个人同时说话,其他人基本上就听不清楚内容了。

解决这个问题的方法一般有音频选路和服务端混音两种。但在万人房间的场景下这两种解决方案都有所缺陷:

  • 音频选路是在 N 路音频中选择音量最大的几路进行下发(一般 2~3 路)。这个方案确实能够解决上述问题,但它有一个前置条件:与客户端直连的边缘服务器上必须汇集全量的音频流,这样才能选路。所以,即使是 48 核的服务器,也难以支持万路并发。
  • 服务端混音是解码 N 路混成1路,或者选路之后再解码3路混成1路。前者的问题主要是MCU 服务器很难顶住这么大的转码压力,而且耗时过长。后者还是会有上述音频选路的缺陷。其实MCU最大的缺点是单点问题,崩溃后会影响全量的用户,很容易成为系统瓶颈。

网易云信的分布式选路

为了解决音频的上述问题,我们采用了在服务器级联之前预选路的方案。假设一个万人房间平均分布在 20 台边缘服务器上,每台服务器有 500 路上行流,如果不使用级联预选路,那么每台服务器互相级联后,都需要拉全量的 10000 路流才能供下行选路使用。

当我们使用级联预选路方案后(默认 3路),每台服务器只需要拉  3x(20-1) 路流就可以,之后再从本机的 500 路流加上级联的 3x(20-1) 路流中进行二次选路,选出最终音量最大的3路流下发给客户端。通过这种方式,实现音频的全订阅。假设在 M 台服务器上传输 N 路音频流,服务器传输数据量的数量级就从 N^2 下降到 M^2。

视频的技术难点

Simulcast/Svc 和码率压制在大房间的局限

由于客户端性能限制,一般能同时解码渲染的视频流路数不会太多,可以通过“被订阅才发流”这种方式来规避上述媒体并发问题。

万人房间的视频技术难点主要在于 QoS,RTC 中服务端的 QoS 手段主要有两个:

  • 利用 Simulcast/Svc 切流
  • 通过 RTCP 压制发送端编码码率

Simulcast 和 Svc 的本质是将用户的下行带宽分层在分发对应的流,但在万人房间中,用户带宽往往分布很散,机械的分层并不能让大多数用户都有最好的体验。RTCP 码率压制是根据接收端带宽反馈给发送端的编码器,编出最适合的码率,其最适用的场景是 1v1,在万人房间中会很难决策。

网易云信 QoS 策略

为了让尽可能多的用户都获得匹配其网络的视频流,我们制定了如下的 QoS 策略:首先我们会根据下行带宽将用户从高到低分为4个层级,发送端同时使用 Simulcast+Svc 编码,例如720p/30fps,720p/15fps,720p/8fps,180p/30fps,服务器根据用户层级为其分配对应的数据流。

这种方法的优点是能够实现每一个用户都能匹配对应其带宽的视频流,但有一个显而易见的缺点,就是分配不够平均。比如一个万人房间中,大部分用户的带宽都命中 720p/15fps 这一层,其它少量用户分散在另外三层上,那么实际上这个房间大多数用户的视频体验都不是最佳。

为了解决这个问题,还需要在分层编码的基础上再结合码率压制:首先将用户的带宽按照从高到低排序,取 topN% 用户的最低带宽反馈给发送端,指导最高层级 (720p/30fps) 的编码码率,以此让 topN% 的用户都能命中体验最好的数据流。N 可以用户设置,也可以根据房间内用户的下行带宽情况动态变化。

下图以 Top60% 举例:

还有一种场景是当用户上行带宽不足时,假设只有 1.2M,根本无法实现 Simulcast+Svc。这种情况下,我们会让客户端只编码一路 720p 的单流,然后在房间中引入一个 MCU,将单流转发给它,MCU 在转码时再使用 Simulcast+Svc,并回推给 SFU,以此来匹配我们的下行 QoS 策略。

服务器之间网络传输的技术难点

跨运营商和跨国传输

实际开发的过程中,我们还遇到了一些服务器之间网络传输问题,这里也和大家分享一下。

比如为了减少最后一公里距离,我们会使用一些单线机房作为边缘节点,不同运营商的单线机房如果直接级联,他们的网络传输很明显是不可控的。想要从架构层面解决这个问题,就必须在级联网络中再引入一个三线/BGP 机房作为中转,而这又要考虑中转服务器的节点位置分配和单点崩溃问题,这样无疑大大增加了调度的复杂性。

另一种情况是跨国场景下的机器级联,服务器之间的公网路由不一定是最优,抖动也可能非常大,中间一公里的网络完全不可控。

WE-CAN

为了解决类似问题,我们将服务器之间的传输模块抽象出来,引入了自己的公网基建,大规模分布式实时传输网:WE-CAN(Communications Acceleration Network)。在全球主要地区都部署节点,节点之间不断探测网络质量并上报,中心决策模块收到上报后综合运营商,实时网络质量,带宽成本等信息后计算任意两个节点之间的最短路径并生成路由表,再下发给各个节点作为下一跳的路由参考。WE-CAN 跟业务无关,完全是传输层解决方案。通过这种方式,媒体级联只需要在包头打上目标地址,再投递给 WE-CAN,完全不需要考虑业务之外的传输问题。

总结

以上技术方案就是本次分享的全部内容,通过云信的万人连麦技术,将服务升级为无状态,不需要限制房间最大人数和同时上麦人数,并且支持水平弹性扩容,轻松应对突发流量,秒级匹配用户网络。

当然任何系统的搭建都不是一蹴而就的,其中每一个点,我们都是踩坑无数。网易云信也将继续打磨音视频技术,给行业带来更好的服务。

作者介绍

陈策,网易云信资深音视频服务端开发工程师,负责云信全球 RTC 网络的搭建和担任核心开发,在媒体数据传输和 RTC 全栈架构设计方面有丰富的经验。