本文经作者授权转载,如需转载,请与原作者联系
本文作者:张鹏,音视频工程师(原文地址)
概述
在开发流媒体服务器时,rtp数据如何在服务器之间转发,对于降低音视频延时和丢包有很重要的影响。
我设想了一种可以降低音视频延时的转发方案。思想来源于IP协议的路由表选路算法。
TCP UDP协议的区别
我们经常说tcp和udp的区别是,tcp是有连接的,udp是无连接的。
TCP的有连接
什么是连接?
连接就是一个固定的路径,这个路径是由网络上一些路由器、交换机组成。这个连接途经的设备是固定的,这些是在tcp创建连接时选定的。
如何选择这些路径呢?
在TCP创建连接时,经过IP协议中的路由表算法,查找当前最优路径,来确定了这么一条路径。并且将一些地址映射关系存储在了途径的路由器设备中,占用了设备的少量内存。但是问题在于,这个路径在一开始是最优的,在传输过程中,可能就不是最优的了。这就导致了tcp连接网速的不稳定。
UDP的无连接
UDP协议就不同了,它不需要创建连接的过程,也就不需要提前选定途径的设备。针对每一个单独的UDP数据包,单独选择当前最优路径,从而达到低于TCP的延时。总体来看,当网络不稳定时,UDP转发数据,由于会选择对单个发送最优的路径,所以速度会优于TCP协议。
两者的区别
本文关注的TCP UDP之间的区别,主要是路径选择,也就是IP协议中的路由表算法,是在什么时机起作用的。
媒体服务器的设计
对比了TCP UDP的选路算法的区别,是为了利用在媒体服务器上。媒体服务器就是转发UDP数据的RTP服务器,它的作用就相当于网络中路由器和交换机。我们把媒体服务器设计成一个模拟IP协议的应用服务器。
地址
UDP协议由于每个包都需要单独选路,并且无连接。中间的路由设备只根据payload是不知道应该某个包发到哪里去的。所以每个UDP包必须携带头部信息,头部信息中最重要的是目的地址、源地址信息。同样的我们的服务器集群中,应该定义一个地址空间。
假如地址是这样设计的:
1| 目的服务器index| sessionid | userid |
2| 源服务器index |sessionid | userid |
3| RTP 头部 |
4| UDP 头部 |
5| payload |
第一行表示,目的地址,定位接收用户。
第二行表示,发送地址,定位发送用户。
- 服务器index:整个集群中某个服务器的id,从1开始
- sessionid:某服务器上某一个session的id,从1开始
- userid:某session中一个user的id,从1开始
这样的一个地址,唯一确定了某个接入的用户,在集群的哪个服务器接入,属于哪一个会议,是谁。
转发过程
用户A的地址为:1|1000|1
用户B的地址为:10|2000|2
A将UDP包发给服务器1,由于目的地址是中服务器index是10,所以查找路由表:
路由表查询结果为 1->10: 1–>3–10
即,从服务器1到服务器10,最短路径需要经过服务器3转发。
服务器1将数据包转发给服务器3
服务器3同样的查找路由表,将数据发送给服务器10
服务器10,发现目的地址是自己,查找session id,再查找userid,将数据发送给用户B
路由表的维护
媒体服务器之间需要互相发送探测包,探测各个服务器之间的延时,丢包率。
将数据上报给媒体控制服务器MCS。
MCS定期计算路由表,将新路由表推送给zookeeper。
由zookeeper下发路由表到各个媒体服务器。
媒体服务器的故障
当某台媒体服务器故障时,会自动在最新的路由表中删除该节点。不会影响媒体数据的转发。增加新的媒体服务器,只需要注册到zookeeper和MCS即可。后续的路由表,会自动加入该节点。
优化的方向
媒体服务器的实现逻辑越靠近IP协议,转发就越有效率,服务器集群就越稳定,容灾能力就更强。所以后续多研究IP协议的实现,对实现媒体服务器有很大的帮助。
丢包重传
媒体服务器可以对数据包进行缓存,并处理nack请求。由于一段时间内路由表是稳定的,nack请求会已最短路径的方式,到达曾经rtp包途径的服务器,每个服务器都可以通过本地缓存处理nack。同时,服务器之间发包应该由下一级服务器检测丢包,及时向上级请求重传。客户端接入的服务器,也应该运行丢包检测,及时检测到丢包,并请求重传。服务器通过及早发现丢包,及早重传包,降低重传包到达客户端的延时。