本文将介绍 RTP 数据包在现实世界中如何跨网络发送,以及随之而来的一些挑战。内容来自 Webex 的首席工程师和架构师 Rob Hanton 的分享。
RTP 传输
虽然大多数互联网流量都基于 TCP,但实时媒体一般都通过 UDP 发送。TCP 和 UDP 之间有一些主要区别:
属性 | TCP | UDP |
---|---|---|
连接状态 | 需要先建立连接才能发送任何数据。 | 无连接;数据包由发送方自行选择传输。 |
方法 | 数据以连续流的形式发送,没有内置的分段或边界。 | 数据以具有明确边界的离散数据包形式发送。 |
可靠性 | 数据传送有保证,具有内置确认和重传功能。 | 不保证数据包的传送;没有内置确认和重新传输。 |
排序 | 保证按发送顺序接收数据。 | 数据包的接收顺序可以与发送顺序不同。 |
UDP 与 TCP 的比较
在上表中比较 TCP 和 UDP 时,我们会发现 UDP 是一个简单得多的协议,不存在使 TCP 变得可靠和有序的反馈和确认。这意味着,通过 UDP 发送的媒体的延迟一般比 TCP 低得多,因此,在延迟很重要的情况下,UDP 比 TCP 更受青睐,尽管这样做会带来很大的复杂性,需要应对 UDP 的有损、无序特性。如果 UDP 不可用,TCP 仍可作为备用,并且可以在延迟要求不太严格的情况下优先使用,例如通过 Facebook Live 等平台进行单向流式传输。
由于 UDP 的无连接特性,防火墙或 NAT 有可能会阻止媒体。解决这一问题的最有效方法是一套称为交互式连接建立(ICE)的技术,这可能会在以后的系列文章中介绍。
不过,缓解这一问题的一个简单方法是通过对称端口——实现应在用于接收媒体的同一端口上发送媒体流的 RTP。这样做的原因是,大多数 NAT 和防火墙在发送传出流量时,也会暂时允许同一端口的传入流量,并将其路由回防火墙内发送方的 IP 地址。这些临时开放的端口被称为 “pinholes”。调试时,如果双向流(如主音频和视频)正常工作,但单向流(如内容视频)失效,罪魁祸首往往是 NAT 或防火墙由于 pinholes 而允许双向流通过,但却阻止了没有开放 pinholes 的单向流。
实现通常在使用时从临时端口范围内动态分配端口。RFC6335 建议使用 49152-65535 作为动态临时端口。虽然使用此端口范围非常普遍,但其他人可能会使用 Linux 端口范围 32768-60999 或其他范围。端口范围通常应由管理员配置,以允许他们遵守企业政策。但是,对于许多客户可以访问的基于云的服务,建议使用更窄的范围,因为许多企业出于安全或政策原因不喜欢开放对大量外部端口的访问。如果可能的话,在这种情况下,最好通过多路复用支持仅使用单个一致的端口进行所有流量 ,以最大限度地减少企业必须打开的端口数。
当未使用多路复用时,每个并发呼叫中的每个媒体流都需要自己的端口以及 RTCP 端口。按照惯例,这些端口通常是一对,RTP 位于偶数端口上,而 RTCP 位于编号高一个的端口上。绑定这些端口对时,一种简单的技巧是在不指定端口的情况下在动态范围内绑定 UDP 套接字,一旦成功,尝试绑定高一个端口(如果最初绑定的端口是偶数)或低一个端口(如果绑定的端口是奇数)。如果第二次绑定失败(这应该只在另一个应用程序与端口范围争用时发生),则应释放初始端口并尝试新的端口,直到成功绑定一对端口或达到尝试次数的上限。
请注意,根据 Offer/Answer SDP (RFC3264) 的规则,一旦实现发送了 SDP,它们就应该准备好接收 SDP 所宣传支持的任何媒体流。事实上,由于媒体路径通常比信令路径更简单、更快,因此媒体数据包在 SDP Answer 或 ACK 之前到达的情况很常见。对于未加密的媒体,实现理想情况下应该在收到媒体后立即开始呈现媒体。对于加密媒体,这通常是不可能的,因为加密密钥尚未收到,但至少系统应该接收数据包并妥善丢弃它们,直到它们可以被处理,同时不生成诸如 ICMP 无法到达响应之类的指示。
发送 RTP 数据包
数据包大小和 MTU
UDP 数据包具有最大大小,称为最大传输单元 (MTU)。但是,不同的网络链路有不同的最大值,而不是标准值。实际上,给定路径上任何一跳的最小 MTU 决定了路径 MTU。
确保 RTP 数据包不超过路径 MTU 尤为重要。如果使用的是 IPv4,则超过路径 MTU 的数据包可能会被分段,并可能在传送到远端之前自动重新组装,但 IP 分段由于一系列实施和安全原因而非常不可靠(有关更多详细信息,请参阅RFC8900),超大数据包很可能永远不会到达其预期目的地。但是,MTU 越低,数据包标头相对于 RTP 有效负载数据的开销就越大,传输效率就越低,因此越接近最大数据包越好。
遗憾的是,虽然有自动发现路径 MTU(路径 MTU 发现或 PMTUD)的技术,但它们并不总是有效的,并且如果先运行,将延迟媒体的启动。因此,大多数实现都依赖于可配置的 MTU,其默认值相对保守,可以由用户或管理员覆盖。以太网数据包的广泛支持的上限是 1500 字节(这意味着在最小 20 字节 IP 报头大小和 8 字节 UDP 报头的情况下,最大 RTP 数据包大小为 1472 字节),但由于某些网络跳跃可能会引入额外的开销或限制稍低;1400 通常是为企业网络设计的设备的默认值,而寻求最大互操作性的实现则更低:例如,Chrome 目前对 WebRTC 使用的最大 RTP 数据包大小为 1200。
Packet Pacing
请注意,虽然 RTP 数据包的最大容量小于 1.5kB,但媒体帧可以而且将会被分割到 RTP 数据包中;视频关键帧被分割到几十个甚至上百个数据包中的情况并不少见。具体方法取决于编解码器和各种因素,如 H.264 中的分包模式。
相比之下,音频帧要小得多,通常可以装入单个数据包中。实际上,一些实现将多个音频帧包含在单个数据包中,以通过减少每帧的开销来节省带宽,但这会增加延迟,因为在对数据包中的后续帧进行采样和编码之前无法发送第一帧,因此这种技术通常不值得节省带宽。
但是,将帧拆分到大量数据包中会导致需要进行 Packet Pacing。实时媒体最简单的实现就是在编码器生成数据包后立即将其放到线路上,但这对视频来说可能会有问题,尤其是在高分辨率下,关键帧或突然变化的时间段可能会导致涉及数百个 RTP 数据包的帧。突然发送所有数据包可能会暂时大大超出协商的带宽限制,从而导致网络拥塞并导致缓冲区膨胀或数据包丢失。
Packet pacing 通常涉及在编码器后 添加一个小型FIFO缓冲区 ,以便以更统一的方式将数据包定速发送到线路上,从而缓解这种突发性。有多种方法可以实现这一点;一种常见的模式是leaky bucket,它允许控制带宽和突发性。每个媒体流都可以独立定速,也可以有一个缓冲区结合多个传出流;这将更复杂地实现,但可以设计为确保在竞争激烈时优先处理较小的流(例如音频)。请注意,一些服务使用 Linux tc (流量控制)模块来启用数据包定速,而不是使用本机实现。
服务质量 (QoS)
为改善可靠性和延迟,可以采取的另一个步骤是在数据包上设置适当的服务质量 (QoS) 标记。QoS 是一种允许路由器和交换机对流量进行分类以适当确定其优先级的做法。在实时媒体中,这通常使用RFC2474中定义的差分服务代码点 (DSCP) 标记来完成,它是 IP 报头中的一个 6 位字段,可帮助路由器和交换机对数据包内的流量类型进行分类。
实现通常不需要担心 DiffServ 机制或写入 IP 数据包头,这些机制通常会在较低级别处理;实时媒体实现的重要部分是选择适当的流值并确保在发送数据包的套接字上设置这些值。
有多个 RFC 讨论了如何最好地标记各种数据包流(通常是RFC4594,特别是在 WebRTC 环境中的RFC8837 )。 他们通常建议为音频流分配最高优先级和延迟不容忍度,他们建议将其标记为加急转发(EF),值为 46,而视频应标记为保证转发(AF),值为 34(对于 AF41),其他数据包流的值较低。 许多实现都遵循这些建议,但也建议任何针对大型企业使用的实现都允许管理员配置这些值,因为他们可能有自己希望所有应用程序遵循的特定 QoS 策略。
可以将 DSCP 设置在更细粒度的级别,根据特定有效负载对给定媒体流内的不同数据包应用不同的标记,例如对使用时间或空间可伸缩性编码的 H.264 流中可丢弃层的数据包应用较低的 DSCP 值;然而,很少有实现能走到这一步。
值得注意的是,为音频和视频设置不同级别的 QoS 的常见做法可能会导致它们通过网络采用不同的路径,从而导致它们不同步,并且需要一个延迟才能与另一个实现口型同步。因此,有人认为,如果音频和视频流需要同步,则它们应该应用相同的 DSCP 标记,以尽量减少流之间的差异延迟,而不是将音频标记为比其匹配的视频更重要/延迟不容忍。
原文:https://blog.webex.com/engineering/rtp-transmission-coping-with-real-networks/
本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/56450.html