用于高带宽应用的 WebRTC 数据通道

WebRTC Datachannel for high bandwidth application

我想通过 WebRTC 数据通道发送单向流数据,正在寻找最佳配置选项(高 BW,低 latency/jitter)以及其他人在此类应用程序中对预期比特率的体验。

我的测试程序发送 2k 块,带有 2k 的 bufferedAmountLowThreshold 事件回调并再次调用发送,直到 bufferedAmount 超过 16k。在 Chrome 中使用它,我实现了 ~135Mbit/s 的 LAN 和 ~20Mbit/s from/to 远程连接,两端都有 100Mbit/s 的 WAN 连接。

这里的限制因素是什么?

如何查看数据是否真正直接点对点传输,或者是否使用了 TURN 服务器?

我的最终应用程序将在 Android 上使用 google-webrtc 库 - 我只使用 JS 进行原型制作。我可以设置选项来加快库中的比特率,这是我在官方 JS API 中无法做到的吗?

影响吞吐量的变量有很多,而且很大程度上取决于您的测量方式。但我将列出一些我为提高 WebRTC 数据通道的吞吐量而调整的内容。

免责声明:我没有为 libwebrtc 做这些调整,而是为我自己的名为 RAWRTC 的 WebRTC 数据通道库做这些调整,顺便说一下,它也为 Android 编译。但是,两者在底层使用相同的 SCTP 库,都使用一些 OpenSSL-ish 库和 UDP 套接字,因此所有这些都应该适用于 libwebrtc。

请注意,使用 usrsctp 的 WebRTC 数据通道实现在同一台机器上执行时通常 CPU 绑定,因此在测试时请记住这一点。使用 RAWRTC 的默认设置,我可以在我的 i7 5820k 上达到 ~520 Mbit/s。根据我自己的测试,Chrom(e|ium) 和 Firefox 都能够在默认设置下达到 ~350 Mbit/s。

好的,让我们深入了解调整...

UDP Send/Receive 缓冲区大小

Linux 中 UDP 套接字的默认 send/receive 缓冲区默认非常小。如果可以的话,不妨调整一下。

DTLS 密码套件

大多数 Android 设备都具有不支持硬件 AES 的 ARM 处理器。 ChaCha20 通常在软件中表现更好,因此您可能会喜欢它。

(这是RAWRTC默认协商的,所以我没有把它包含在最终结果中。)

SCTP Send/Receive 缓冲区大小

usrsctp(libwebrtc 使用的 SCTP 堆栈)的默认 send/receive window 大小,is 256 KiB 太小了,无法以中等延迟实现高吞吐量。理论上的最大吞吐量受到 mbits = (window / (rtt_ms / 1000)) / 131072 的限制。因此,使用 window=262144 的默认 window 和相当适中的 rtt_ms=20 RTT,您最终将得到理论上的最大值 100 Mbit/s.

实际最大值低于此...实际上,远低于理论最大值(参见 my test results). This may be a bug in the usrsctp stack (see sctplab/usrsctp#245)。

Firefox 中的缓冲区大小已增加(请参阅 bug 1051685),但 Chrom(e|ium) 使用的 libwebrtc 中没有。

发布版本

优化级别 3 有所作为(呃!)。

邮件大小

您可能想要发送 256 KiB 大小的消息。

除非你需要支持 Chrome < ??? (抱歉,我目前不知道它落在哪里...),那么最大消息大小为 64 KiB(请参阅 issue 7774)。

除非您还需要支持 Firefox < 56,在这种情况下最大消息大小为 16 KiB(参见 bug 979417)。

这还取决于您在暂停发送之前发送了多少(即缓冲区的高水位线),以及在缓冲区耗尽后继续发送的时间(即缓冲区的低水位线)。我的测试表明,针对 1 MiB 的高水位标记 并设置 256 KiB 的低水位标记 会产生足够的吞吐量。

这会减少 API 调用量,并且 可以 提高吞吐量。

最终结果

在 RAWRTC 上使用默认设置的优化级别 3 使我达到了 ~600 Mbit/s。

基于此,将 SCTP 和 UDP 缓冲区大小增加到 4 MiB 使我进一步达到 ~700 Mbit/s,其中一个 CPU 核心处于 100% 负载。

不过,我相信仍有改进的空间,但不太可能 low-hanging。


How can I see if the data is truly going peer to peer directly, or whether a TURN server is used?

在 Firefox 中打开 about:webrtc 或在 Chrom(e|ium) 中打开 chrome://webrtc-internals 并查找所选的 ICE 候选对。或者使用 Wireshark。