级联SFU:提高WebRTC应用程序中媒体的可伸缩性和质量

为WebRTC部署媒体服务器有两个困难:扩展,即 不仅使用一台服务器,还为所有会议用户优化了延迟。 尽管本着“将X会议的所有用户发送到服务器Y”的精神进行简单分片很容易进行水平扩展,但就延迟而言,它并不是最佳选择。 在不仅靠近用户而且还相互连接的服务器之间分配会议,听起来像是对这两个问题的解决方案。 今天,我们准备了来自Jitsi的Boris Grozev的详细材料的翻译:级联SFU的问题,并介绍了方法和一些困难以及实现细节。 值得一提的是,Voximplant会议还使用SFU 。 我们目前正在研究SFU的级联,该级联将于明年在我们的平台上出现。


小鼠神经元。 NIHD影像( CC-BY-2.0

实时通信对网络非常敏感:带宽,延迟和数据包丢失。 比特率的降低导致视频质量的降低,长时间的网络延迟导致最终用户的长时间延迟。 数据包的丢失会使声音断断续续,并导致视频冻结(由于跳帧)。

因此,对于会议而言,在终端设备/用户之间选择最佳路由非常重要。 只有两个用户时,这很容易-WebRTC使用ICE协议在参与者之间建立连接。 如果可能,参与者直接连接,否则使用TURN服务器。 WebRTC可以解析域名来获取TURN服务器的地址,因此您可以轻松地基于DNS选择本地TURN,例如,使用AWS Route53属性。

但是,当通过一个中央媒体服务器进行多个参与者的路由时,情况变得复杂。 许多WebRTC服务使用选择性转发单元(SFU)在3个或更多参与者之间更有效地传输音频和视频。

明星问题


在星形拓扑中,所有参与者都连接到单个服务器,通过它们他们可以交换媒体流。 显然,服务器位置的选择非常重要:如果所有参与者都位于美国,那么在悉尼使用服务器不是一个好主意。


许多服务使用一种在大多数情况下都能正常工作的简单方法:他们选择一个靠近会议第一位参与者的服务器。 但是,有时这种解决方案不是最佳的。 想象一下,上图中有三位参与者。 如果一个澳大利亚人(呼叫者C)是第一个参加会议的人,则该算法将选择澳大利亚的服务器,但是美国的Server 1将是最佳选择,因为 他更接近大多数参与者。

所描述的情况不是很频繁,但是确实发生了。 如果我们假设用户是以随机顺序连接的,则在所有3人参加的会议中,有1/3发生了上述情况,其中一个会议被非常删除。

另一个更常见的场景:我们有两组参与者位于不同的位置。 在这种情况下,连接顺序并不重要,我们将始终有一群位置紧密的参与者,他们被迫与远程服务器交换媒体。 例如,来自澳大利亚(C&D)的2位参与者和来自美国(A&B)的2位参与者。


对于C&D成员来说,切换到服务器1并不是最佳选择。 服务器2对于A&B并非最佳。 也就是说,无论使用什么服务器,总是会有参与者连接到远程(=非最佳)服务器。

但是,如果我们没有单个服务器的限制? 我们可以将每个参与者连接到最近的服务器,仅保留这些服务器的连接即可。

解决方案:级联


我们推迟了如何连接服务器的问题。 我们先来看一下效果。


C和D之间的SFU连接没有更改-服务器2仍在使用,服务器1用于参与者A和B,这显然更好。 最有趣的是例如A和C之间的连接:路由A <=>服务器1 <=>服务器2 <=> C代替了A <=>服务器2 <=>C。

对汇率的隐含影响


SFU组合有其优点和缺点。 一方面,在上述情况下,当在网络上添加新的跳转时,参与者之间的交换时间变得更长。 另一方面,谈论“客户端”-“第一台服务器”连接的时间有所减少,因为我们可以按照逐跳的原理以较低的延迟还原媒体流。

如何运作? WebRTC使用RTP(通常通过UDP)传输媒体。 这意味着运输是不可靠的。 当UDP数据包丢失时,您可以忽略该丢失或使用RTCP NACK数据包请求重新发送(重传)-选择已经在应用程序的良心上。 例如,取决于是否需要解码后续帧,应用程序可能会忽略音频数据包的丢失,并请求重发一些(但不是全部)视频数据包。


RTP数据包重传,单个服务器

当有级联时,可以将重发限制在本地服务器上,即在每个单独的站点上执行。 例如,在路由A-S1-S2-C中,如果在A和S1之间丢失了一个数据包,则S1将注意到这一点并请求重传; 类似于S2和C之间的丢失。即使在服务器之间丢失了数据包,接收方也可能会请求重传。


RTP数据包重传,两台服务器。 请注意,服务器2不请求数据包2,因为NACK在发送数据包后不久到达。

客户端使用抖动缓冲区来延迟视频播放,并设法接收延迟/重传的数据包。 缓冲区大小根据双方之间的交换时间动态变化。 当出现逐跳重传时,延迟会减少,结果,缓冲区可能会更小-结果,总延迟也会减少。

简而言之:即使参与者之间的交换时间较长,也可以减少参与者之间传输媒体的延迟。 我们尚未在实践中研究这种效果。

引入级联SFU:Jitsi Meet Case


警报与 媒体类


让我们看看警报。 从一开始,Jitsi Meet便共享了信令服务器( Jicofo )和媒体服务器/ SFU的概念。 这使得引入级联支持相对简单。 首先,我们可以在一个地方处理所有信令逻辑。 其次,我们已经在Jicofo和媒体服务器之间建立了信令协议。 我们只需要稍微扩展一下功能:我们已经支持了连接到一个信令服务器的多个SFU,我们必须增加一个SFU连接到许多信令服务器的功能。

结果,出现了两个独立的服务器池:一个用于jicofo实例,另一个用于媒体服务器实例,请参见下图:


在AWS上组织服务器的示例,其中可能在不同的数据中心之间进行级联。

该系统的第二部分是桥对桥通信。 我们希望使这一部分尽可能简单,因此在网桥之间没有复杂的信令。 所有警报都在jicofo和jitsi-videobridge之间; 网桥连接仅用于音频/视频和数据链接消息。

八重协议


为了管理这种交互,我们采用了Octo协议,该协议将RTP数据包包装在简单的固定长度报头中,并且还允许您发送文本消息。 在当前的实现中,网桥通过全网状拓扑(全网状)连接,但是其他拓扑也是可能的。 例如,对每个网桥使用中央服务器(网桥为星型)或树结构。

说明:不用将其包装在Octo头中,可以使用RTP头扩展名,该扩展名将在纯(S)RTP上的网桥之间进行流动。 Octo的未来版本可以使用这种方法。

第二个解释:Octo毫无意义。 首先,我们想使用中央服务器,它使我们想起了章鱼。 因此,该项目的名称出现了。

八度标题格式

用Jitsi术语来说,当一个网桥是具有多个网桥的会议的一部分时,它具有一个附加的Octo频道(实际上,一个频道用于音频,一个频道用于视频)。 该通道负责向/从其他网桥发送/接收媒体。 每个网桥都为Octo分配了一个空闲端口(默认为4096),因此我们需要会议ID字段来处理多个会议。

目前,该协议没有内置的安全机制,因此我们将此责任委托给较低级别​​。 这是我们在不久的将来会做的最接近的事情,但是目前,网桥应该位于安全的网络中(例如,单独的AWS VPC实例)。

同播


同播允许每个参与者发送具有不同比特率的多个媒体流,而网桥则可以帮助确定需要哪些媒体流。 为了使此正常工作,我们在网桥之间传输所有联播流。 因此,您可以在流之间快速切换,因为本地网桥不需要请求新的流。 但是,从桥到桥交通的角度来看,这并不是最佳选择,因为 一些线程很少使用,并且只是无目的地加载带宽。

活跃会员选择


我们还希望有机会订阅会议的积极参与者/发言人。 事实证明这很简单-我们教导每个网桥独立确定主要参与者,然后通知我们的本地客户。 这意味着确定需要进行多次,但并不昂贵,并且可以简化一些要点(例如,您无需确定哪个桥应该负责DSI ,而不必担心路由消息)。

桥梁选择


在当前的实现中,此算法很简单。 当新的参与者加入会议时,Jicofo必须确定分配给他的桥梁。 这是基于参与者的区域和桥梁的拥挤程度来完成的。 如果在同一地区有一座自由桥梁,则将其任命。 否则,将使用其他桥。

有关Octo的更多信息,请参阅文档

展开级联SFU


为了进行部署,我们使用了Amazon AWS中的机器。 我们在6个地区拥有服务器(警报和媒体):

  • us-east-1(北弗吉尼亚);
  • us-west-2(俄勒冈);
  • eu-west-1(爱尔兰);
  • eu-central-1(法兰克福);
  • ap-se-1(新加坡);
  • ap-se-2(悉尼)。

我们使用了地理参考的HAProxy实例来确定成员区域。 Meet.jit.si域由Route53管理,并解析为HAProxy实例,该实例将区域添加到已发送请求的HTTP标头中。 该标头稍后将用作config.deploymentInfo.userRegion变量的值,由于/config.js文件,该变量可在客户端上使用。

jitsi界面显示了使用了多少个网桥以及连接了哪些特定用户-用于诊断和演示目的。 将鼠标悬停在本地视频的左上角将显示服务器总数和您连接到的服务器。 同样,您可以看到第二个参与者的参数。 您还将看到您的浏览器和对话者的浏览器之间的交换时间(参数E2E RTT)。


通过查看谁连接到哪个服务器,可以查看是否使用了级联。

结论


Octo最初作为A / B测试出现。 最初的结果很好,所以现在Octo可供所有人使用。 仍然有大量流量要通过,并仔细研究性能。 还计划利用这些开发成果来支持更大的会议(当一个SFU不够用时)。

Source: https://habr.com/ru/post/zh-CN432708/


All Articles