searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享

通过级联 SFU 提高规模和媒体质量

2023-05-12 00:57:17
88
0

为 WebRTC 部署媒体服务器有两个主要挑战,扩展到单个服务器之外,以及优化会议中所有用户的媒体延迟。虽然简单的分片方法(如“将会议 X 中的所有用户发送到服务器 Y”)很容易水平扩展,但它们在媒体延迟方面远非最佳,而媒体延迟是用户体验的关键因素。将会议分发到靠近用户并在可靠主干上相互连接的服务器网络,可以同时解决这两个问题。来自Jitsi团队的Boris Grozev深入描述了级联SFU问题,并展示了他们的方法以及他们遇到的一些挑战。

实时通信应用程序对吞吐量、延迟和丢失等网络条件非常敏感。较低的比特率会导致较低的视频质量,较长的网络延迟会导致音频和视频的端到端延迟更长。由于视频跳帧,丢包会导致音频和视频“断断续续”冻结。

因此,在会议中的端点之间选择最佳路径非常重要。当只有两个参与者时,这是相对简单的 - WebRTC使用ICE协议在两个端点之间建立连接以交换多媒体。如果可能,两个端点直接连接,否则在不太典型的情况下使用 TURN 中继服务器。WebRTC 支持解析域名以获取 TURN 服务器地址,这使得基于 DNS 选择本地 TURN 服务器变得容易,例如通过使用 AWS Route53 的路由选项。

但是,当会议有更多的参与者通过集中式媒体服务器路由时,情况要复杂得多。许多WebRTC服务,如环聊,appear.in,Slack和我们自己的 meet.jit.si,使用选择性转发单元(SFU)在3个或更多参与者之间更有效地中继音频和视频。

星形问题


在这种情况下,所有端点都连接到中央服务器(在星形拓扑中),并与之交换多媒体。很明显,选择服务器的位置对用户体验有巨大的影响——如果会议的所有参与者都位于美国,那么使用悉尼的服务器不是一个好主意。

大多数服务使用一种简单的方法,这种方法在很多时候都运行良好 - 它们选择靠近会议中第一个参与者的服务器。但是,在某些情况下,这不是最佳的。例如,假设我们有三个参与者 – 两个位于美国东海岸,第三个位于澳大利亚。如果澳大利亚参与者(呼叫者 C)首先加入会议,则此算法将选择澳大利亚的服务器(服务器 2),但美国的服务器 1 是更好的选择,因为它更接近大多数参与者。

这样的场景并不常见,但它们确实会发生。

另一种更频繁发生的场景:我们在两个地点有两组参与者。在这种情况下,加入的顺序无关紧要,我们将始终有一些彼此靠近的用户对,但他们的媒体必须通过远程位置的服务器。例如,有 2 个澳大利亚呼叫者 (C&D) 和 2 个美国呼叫者 (A&B)。

切换到服务器 1 对于呼叫者 C&D 不是最佳选择,服务器 2 对于呼叫者 A&B 不是最佳选择。无论我们使用服务器 1 还是服务器 2,都会有一些参与者通过非最佳远程服务器连接。

如果我们不限于使用一台服务器会怎样?我们可以让每个参与者连接到本地服务器,我们只需要互连服务器。

解决方案:级联

暂且不谈如何实际互连服务器的问题,让我们先来看看这对会议有什么影响。

从 C 到 D 的 SFU 连接没有改变——仍然通过服务器 2。对于 A 和 B 之间的连接,我们使用服务器 1 而不是服务器 2,这显然更好。有趣的部分实际上是从A到C的连接(或任何其他连接,其效果是相似的)。不使用 A<=>Server 2<=>C,而是使用 A<=>Server 1<=>Server 2<=>C。

非直观的行程时间影响

像这样连接SFU网桥有优点和缺点。一方面,我们的结果表明,在这种情况下当我们添加额外的跃点时,端到端往返时间更高。另一方面,减少从客户端到它所连接的第一台服务器的往返时间本身就具有优势,因为我们可以在逐跳的基础上以较低的延迟执行流修复。

这是怎么回事?WebRTC使用RTP,通常通过UDP,来传输媒体。这意味着运输不可靠。当 UDP 数据包在网络中丢失时,由应用程序忽略/隐藏丢失,或使用 RTCP NACK 数据包请求重新传输。例如,应用程序可能会选择忽略丢失的音频数据包,并请求重新传输部分但不是全部视频数据包(取决于解码后续帧是否需要它们)。

RTP 数据包使用单个服务器进行传输。

使用级联网桥,这些重新传输可以限制为本地服务器。例如,在 A-S1-S2-C 路径中,如果 A 和 S1 之间的数据包丢失,S1 将通知并请求重新传输。如果 S2 和 C 之间的数据包丢失,C 将请求重新传输,S2 将从其缓存响应。如果两个服务器之间的数据包丢失,接收服务器可以请求重新传输。

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

客户端使用抖动缓冲区来延迟视频的播放,以便允许延迟或重新传输的数据包到达。此缓冲区的大小会根据往返时间动态变化。当逐跳执行重传时,延迟较低,因此抖动缓冲区可以更短,从而降低整体延迟。

简而言之,即使使用额外的服务器,端到端往返时间更高,这可能会导致端到端媒体延迟降低(但我们尚未在实践中探索这种影响)。

实现级联 SFU

那么我们如何在 Jitsi Meet 中实现这一点,以及如何在 meet.jit.si 上部署它呢?

信令与媒体

让我们先看看信令。自成立以来,Jitsi Meet已经分离了信令服务器(现在是Jicofo)和媒体服务器/ SFU(jitsi-videobridge)的概念。这种分离使我们能够相对容易地实现对级联桥梁的支持。首先,我们可以将所有信号逻辑保存在一个中心位置——Jicofo。其次,我们已经有了Jicofo和Jitsi Videobridge(COLIBRI)之间的信令协议。我们只需要添加一个小的扩展。我们已经支持连接到一个信令服务器的多个 SFU(用于负载平衡)。现在,我们必须添加一个 SFU 连接到多个信令服务器的选项。

我们最终得到了两个独立的服务器池——一个是jicofo实例池,一个是jitsi-videobridge实例池。下图说明了其中的一部分。

AWS 上的级联 SFU 服务器到服务器架构图示
AWS 上的 Jitsi Meet 设置示例,允许跨不同数据中心的桥接级联

我们系统的第二部分是桥到桥通信。我们希望使这部分尽可能简单,因此我们决定不在桥之间执行任何显式信号。所有信令都发生在jicofo和jitsi-videobridge之间,两个网桥之间的连接仅用于来自客户端的音频/视频和数据通道消息。

Octo协议

为了协调这种通信,我们提出了Octo协议,它将RTP数据包包装在一个简单的固定长度标头中,并允许传输字符串消息。在当前的实现中,网桥以全网状方式相互连接,但设计也允许其他拓扑。例如,使用中央中继服务器(网桥星形)或每个网桥的树结构。

脚注:请注意,可以将其添加为 RTP 标头扩展,而不是在 Octo 标头前面添加,使网桥之间的流成为纯 (S)RTP。Octo 的未来版本可能会使用这种方法

第二个脚注:Octo并不代表任何东西。 我们最初计划使用中央继电器,出于某种原因,它让我们想起了章鱼,所以我们为这个项目保留了这个名字。

屏幕截图 2018 10 11 在 15.57.53
八进制标头格式

在 Jitsi Videobridge 术语中,当网桥是多桥会议的一部分时,它有一个额外的 Octo 通道(实际上一个用于音频,一个用于视频)。此通道负责将媒体转发到所有其他网桥,以及从所有其他网桥接收媒体。每个网桥绑定到 Octo 的单个端口(默认为 4096),这就是为什么我们需要会议 ID 字段能够一次处理多个会议。

目前,该协议没有自己的安全机制,我们将该责任委托给较低层。这是我们接下来要处理的事情,但目前桥需要位于安全的网络中(我们使用单独的 AWS VPC)。

与联播一起使用

Jitsi Meet 的显着特点之一是联播,每个参与者发送多个不同比特率的流,桥接器有助于选择所需的流。我们希望确保这继续可靠工作,因此我们在网桥之间转发所有联播流。这允许在流之间更快地切换(因为本地网桥不必请求新流)。但是,就网桥到桥流量而言,它不是最佳的,因为某些流通常不使用,只是消耗 exra 带宽而没有任何好处。

当前发言人选择

我们还希望继续支持在会议上关注活跃的演讲者(给他们最大的空间)。事实证明这很容易——我们只是让每个桥独立地进行主要说话人识别,并通知其本地客户(这也是其他人使用的方法)。这意味着计算可以多次完成,但它并不昂贵,并且允许我们简化事情(例如,我们不必决定哪个桥执行DSI,并担心路由消息)。

桥梁选择

使用当前的实现,网桥选择算法很简单。当新参与者加入时,Jicofo需要决定分配给它的桥。它根据客户端的区域以及可用的网桥的区域和负载来执行此操作。如果与客户端位于同一区域中的可用网桥,则使用该网桥。否则,将使用现有的会议桥之一。

有关设置 Octo 的文档,请参阅此处

部署级联 SFU

如上所述,我们现在已经在 meet.jit.si 上启用了地理桥级联。

对于此部署,我们在 Amazon AWS 中运行所有计算机。我们在六个地区拥有服务器(信令和媒体):

  • 美国东部-1(弗吉尼亚北部),
  • 美国西部-2(俄勒冈州),
  • 欧洲西部-1(爱尔兰),
  • 欧盟中部-1(法兰克福),
  • ap-se-1(新加坡)和
  • ap-se-2(悉尼)。

我们使用地理定位的 HAProxy 实例层,这有助于确定客户端来自哪个区域。meet.jit.si 域由 Route53 管理,并解析为 HAProxy 实例,该实例将其自己的区域添加到其转发的请求的 HTTP 标头中。然后,此标头用于设置配置部署信息用户区域变量通过/配置.js文件。

为了进行诊断和演示此功能,meet.jit.si 上的用户界面会显示正在使用的网桥数量以及每个参与者连接到的位置。滚动到本地缩略图的左上角会显示服务器的数量和所连接的服务器的区域。在远程缩略图上滚动会显示远程参与者连接到的服务器区域,以及您的浏览器与其浏览器之间的端到端往返时间(作为 E2E RTT)。

八角注释
您可以通过在 Jitsi Meet 中查看每个人的连接位置来查看是否正在使用网桥级联。

结论

我们最初在八月份推出了 Octo 作为 meet.jit.si 的 A/B 测试。最初的结果看起来不错,现在每个人都可以启用。我们有很多数据要通过,我们计划详细研究Octo的表现,并写更多关于它的文章。我们还计划将这项工作作为支持大型会议(单个SFU是不够的)的第一步。因此,请继续关注未来几个月的更多信息。

 

0条评论
0 / 1000
j****e
12文章数
0粉丝数
j****e
12 文章 | 0 粉丝

通过级联 SFU 提高规模和媒体质量

2023-05-12 00:57:17
88
0

为 WebRTC 部署媒体服务器有两个主要挑战,扩展到单个服务器之外,以及优化会议中所有用户的媒体延迟。虽然简单的分片方法(如“将会议 X 中的所有用户发送到服务器 Y”)很容易水平扩展,但它们在媒体延迟方面远非最佳,而媒体延迟是用户体验的关键因素。将会议分发到靠近用户并在可靠主干上相互连接的服务器网络,可以同时解决这两个问题。来自Jitsi团队的Boris Grozev深入描述了级联SFU问题,并展示了他们的方法以及他们遇到的一些挑战。

实时通信应用程序对吞吐量、延迟和丢失等网络条件非常敏感。较低的比特率会导致较低的视频质量,较长的网络延迟会导致音频和视频的端到端延迟更长。由于视频跳帧,丢包会导致音频和视频“断断续续”冻结。

因此,在会议中的端点之间选择最佳路径非常重要。当只有两个参与者时,这是相对简单的 - WebRTC使用ICE协议在两个端点之间建立连接以交换多媒体。如果可能,两个端点直接连接,否则在不太典型的情况下使用 TURN 中继服务器。WebRTC 支持解析域名以获取 TURN 服务器地址,这使得基于 DNS 选择本地 TURN 服务器变得容易,例如通过使用 AWS Route53 的路由选项。

但是,当会议有更多的参与者通过集中式媒体服务器路由时,情况要复杂得多。许多WebRTC服务,如环聊,appear.in,Slack和我们自己的 meet.jit.si,使用选择性转发单元(SFU)在3个或更多参与者之间更有效地中继音频和视频。

星形问题


在这种情况下,所有端点都连接到中央服务器(在星形拓扑中),并与之交换多媒体。很明显,选择服务器的位置对用户体验有巨大的影响——如果会议的所有参与者都位于美国,那么使用悉尼的服务器不是一个好主意。

大多数服务使用一种简单的方法,这种方法在很多时候都运行良好 - 它们选择靠近会议中第一个参与者的服务器。但是,在某些情况下,这不是最佳的。例如,假设我们有三个参与者 – 两个位于美国东海岸,第三个位于澳大利亚。如果澳大利亚参与者(呼叫者 C)首先加入会议,则此算法将选择澳大利亚的服务器(服务器 2),但美国的服务器 1 是更好的选择,因为它更接近大多数参与者。

这样的场景并不常见,但它们确实会发生。

另一种更频繁发生的场景:我们在两个地点有两组参与者。在这种情况下,加入的顺序无关紧要,我们将始终有一些彼此靠近的用户对,但他们的媒体必须通过远程位置的服务器。例如,有 2 个澳大利亚呼叫者 (C&D) 和 2 个美国呼叫者 (A&B)。

切换到服务器 1 对于呼叫者 C&D 不是最佳选择,服务器 2 对于呼叫者 A&B 不是最佳选择。无论我们使用服务器 1 还是服务器 2,都会有一些参与者通过非最佳远程服务器连接。

如果我们不限于使用一台服务器会怎样?我们可以让每个参与者连接到本地服务器,我们只需要互连服务器。

解决方案:级联

暂且不谈如何实际互连服务器的问题,让我们先来看看这对会议有什么影响。

从 C 到 D 的 SFU 连接没有改变——仍然通过服务器 2。对于 A 和 B 之间的连接,我们使用服务器 1 而不是服务器 2,这显然更好。有趣的部分实际上是从A到C的连接(或任何其他连接,其效果是相似的)。不使用 A<=>Server 2<=>C,而是使用 A<=>Server 1<=>Server 2<=>C。

非直观的行程时间影响

像这样连接SFU网桥有优点和缺点。一方面,我们的结果表明,在这种情况下当我们添加额外的跃点时,端到端往返时间更高。另一方面,减少从客户端到它所连接的第一台服务器的往返时间本身就具有优势,因为我们可以在逐跳的基础上以较低的延迟执行流修复。

这是怎么回事?WebRTC使用RTP,通常通过UDP,来传输媒体。这意味着运输不可靠。当 UDP 数据包在网络中丢失时,由应用程序忽略/隐藏丢失,或使用 RTCP NACK 数据包请求重新传输。例如,应用程序可能会选择忽略丢失的音频数据包,并请求重新传输部分但不是全部视频数据包(取决于解码后续帧是否需要它们)。

RTP 数据包使用单个服务器进行传输。

使用级联网桥,这些重新传输可以限制为本地服务器。例如,在 A-S1-S2-C 路径中,如果 A 和 S1 之间的数据包丢失,S1 将通知并请求重新传输。如果 S2 和 C 之间的数据包丢失,C 将请求重新传输,S2 将从其缓存响应。如果两个服务器之间的数据包丢失,接收服务器可以请求重新传输。

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

客户端使用抖动缓冲区来延迟视频的播放,以便允许延迟或重新传输的数据包到达。此缓冲区的大小会根据往返时间动态变化。当逐跳执行重传时,延迟较低,因此抖动缓冲区可以更短,从而降低整体延迟。

简而言之,即使使用额外的服务器,端到端往返时间更高,这可能会导致端到端媒体延迟降低(但我们尚未在实践中探索这种影响)。

实现级联 SFU

那么我们如何在 Jitsi Meet 中实现这一点,以及如何在 meet.jit.si 上部署它呢?

信令与媒体

让我们先看看信令。自成立以来,Jitsi Meet已经分离了信令服务器(现在是Jicofo)和媒体服务器/ SFU(jitsi-videobridge)的概念。这种分离使我们能够相对容易地实现对级联桥梁的支持。首先,我们可以将所有信号逻辑保存在一个中心位置——Jicofo。其次,我们已经有了Jicofo和Jitsi Videobridge(COLIBRI)之间的信令协议。我们只需要添加一个小的扩展。我们已经支持连接到一个信令服务器的多个 SFU(用于负载平衡)。现在,我们必须添加一个 SFU 连接到多个信令服务器的选项。

我们最终得到了两个独立的服务器池——一个是jicofo实例池,一个是jitsi-videobridge实例池。下图说明了其中的一部分。

AWS 上的级联 SFU 服务器到服务器架构图示
AWS 上的 Jitsi Meet 设置示例,允许跨不同数据中心的桥接级联

我们系统的第二部分是桥到桥通信。我们希望使这部分尽可能简单,因此我们决定不在桥之间执行任何显式信号。所有信令都发生在jicofo和jitsi-videobridge之间,两个网桥之间的连接仅用于来自客户端的音频/视频和数据通道消息。

Octo协议

为了协调这种通信,我们提出了Octo协议,它将RTP数据包包装在一个简单的固定长度标头中,并允许传输字符串消息。在当前的实现中,网桥以全网状方式相互连接,但设计也允许其他拓扑。例如,使用中央中继服务器(网桥星形)或每个网桥的树结构。

脚注:请注意,可以将其添加为 RTP 标头扩展,而不是在 Octo 标头前面添加,使网桥之间的流成为纯 (S)RTP。Octo 的未来版本可能会使用这种方法

第二个脚注:Octo并不代表任何东西。 我们最初计划使用中央继电器,出于某种原因,它让我们想起了章鱼,所以我们为这个项目保留了这个名字。

屏幕截图 2018 10 11 在 15.57.53
八进制标头格式

在 Jitsi Videobridge 术语中,当网桥是多桥会议的一部分时,它有一个额外的 Octo 通道(实际上一个用于音频,一个用于视频)。此通道负责将媒体转发到所有其他网桥,以及从所有其他网桥接收媒体。每个网桥绑定到 Octo 的单个端口(默认为 4096),这就是为什么我们需要会议 ID 字段能够一次处理多个会议。

目前,该协议没有自己的安全机制,我们将该责任委托给较低层。这是我们接下来要处理的事情,但目前桥需要位于安全的网络中(我们使用单独的 AWS VPC)。

与联播一起使用

Jitsi Meet 的显着特点之一是联播,每个参与者发送多个不同比特率的流,桥接器有助于选择所需的流。我们希望确保这继续可靠工作,因此我们在网桥之间转发所有联播流。这允许在流之间更快地切换(因为本地网桥不必请求新流)。但是,就网桥到桥流量而言,它不是最佳的,因为某些流通常不使用,只是消耗 exra 带宽而没有任何好处。

当前发言人选择

我们还希望继续支持在会议上关注活跃的演讲者(给他们最大的空间)。事实证明这很容易——我们只是让每个桥独立地进行主要说话人识别,并通知其本地客户(这也是其他人使用的方法)。这意味着计算可以多次完成,但它并不昂贵,并且允许我们简化事情(例如,我们不必决定哪个桥执行DSI,并担心路由消息)。

桥梁选择

使用当前的实现,网桥选择算法很简单。当新参与者加入时,Jicofo需要决定分配给它的桥。它根据客户端的区域以及可用的网桥的区域和负载来执行此操作。如果与客户端位于同一区域中的可用网桥,则使用该网桥。否则,将使用现有的会议桥之一。

有关设置 Octo 的文档,请参阅此处

部署级联 SFU

如上所述,我们现在已经在 meet.jit.si 上启用了地理桥级联。

对于此部署,我们在 Amazon AWS 中运行所有计算机。我们在六个地区拥有服务器(信令和媒体):

  • 美国东部-1(弗吉尼亚北部),
  • 美国西部-2(俄勒冈州),
  • 欧洲西部-1(爱尔兰),
  • 欧盟中部-1(法兰克福),
  • ap-se-1(新加坡)和
  • ap-se-2(悉尼)。

我们使用地理定位的 HAProxy 实例层,这有助于确定客户端来自哪个区域。meet.jit.si 域由 Route53 管理,并解析为 HAProxy 实例,该实例将其自己的区域添加到其转发的请求的 HTTP 标头中。然后,此标头用于设置配置部署信息用户区域变量通过/配置.js文件。

为了进行诊断和演示此功能,meet.jit.si 上的用户界面会显示正在使用的网桥数量以及每个参与者连接到的位置。滚动到本地缩略图的左上角会显示服务器的数量和所连接的服务器的区域。在远程缩略图上滚动会显示远程参与者连接到的服务器区域,以及您的浏览器与其浏览器之间的端到端往返时间(作为 E2E RTT)。

八角注释
您可以通过在 Jitsi Meet 中查看每个人的连接位置来查看是否正在使用网桥级联。

结论

我们最初在八月份推出了 Octo 作为 meet.jit.si 的 A/B 测试。最初的结果看起来不错,现在每个人都可以启用。我们有很多数据要通过,我们计划详细研究Octo的表现,并写更多关于它的文章。我们还计划将这项工作作为支持大型会议(单个SFU是不够的)的第一步。因此,请继续关注未来几个月的更多信息。

 

文章来自个人专栏
大前端
12 文章 | 2 订阅
0条评论
0 / 1000
请输入你的评论
0
0