12 KiB
26 | 应用层多播:如何快速地分发内容?
你好,我是陶辉。
[第7讲] 我们曾介绍了网络层的IP协议是如何支持多播的,这节课我们再来从应用层看看如何实现多播功能。
当你的分布式集群只有十多个节点时,每次发布版本时,尽可以从发布服务器,将新版本的安装包通过ftp、scp、wget等工具分发到各个节点中。可是,一旦集群规模达到成千上万个节点时,再这么做就会带来很大的问题,文件分发的时长高达几个小时,甚至会打挂文件源终止分发流程。在微服务环境中这点尤为明显, 毕竟每个Docker镜象的体积动辄就在数百兆字节以上。
虽然网络层的IP协议允许通过路由器、交换机实现高效的多播,但IP层很难实现文件的可靠传输,而且跨越多个局域网时路由器等网络设备对IP多播的支持也不好。此时,通过应用层的接力传播,就能通过多播思想大幅提升系统的传输效率,解决上述问题。
除了分发文件场景外,应用层多播协议也常用于完全去中心化的分布式系统,特别是在管理成千上万个节点的状态时非常有用。比如Gossip就是这样一个多播协议,[第22讲] 介绍过的Cassandra数据库使用它来同步节点间的状态,比特币通过它传输账本数据,Redis集群也使用它同步Redis进程间的状态。
那么这节课我们就重点介绍应用层中的多播协议,并以阿里的蜻蜓、Cassandra中的Gossip协议为例,看看它们的工作原理。
认识应用层的多播协议
之所以需要应用层的多播协议,是因为网络层的IP多播功能(参见[第7讲] 的IP广播与组播)有以下4个方面的问题:
- 从功能上看,IP多播缺失了质量控制、可靠性传输等特性,无法满足绝大部分场景中的要求;
- 从管理上看,监控跨网络的多播报文并不容易,多播地址的管理也很复杂,而且多播很容易造成网络洪峰及安全问题;
- 从市场上看,单播报文在终端上的计费很成熟,相反,运营商对多播报文的计费要困难许多,相对缺乏推进动力;
- 从产业协作上看,IP多播必须由各设备厂商的路由器、交换机配合,由于网络层是由内核实现的,所以还要同步升级操作系统。
这些因素都使得网络层的多播功能难以推广,因此,各类基于IP单播功能的应用层多播协议应运而生。可能有些同学对于单播、多播这些网络知识还不熟悉,下图我将传统单播、网络层多播、应用层多播放在一起对比着看,你可以很容易看到它们的区别。
这里仍然以版本发布场景为例,主机1是发布节点,它需要将文件分发到其余3台主机上,其中传统单播协议的玩法,是在主机2、3、4上分别向主机1发起下载文件命令,因此主机1上有3条TCP下载链路,图中我用3种不同的颜色表示。很明显,此时主机1的下行流量一定会成为瓶颈,而且随着集群规模的扩大,网络链路中的路由器也会很快达到流量瓶颈。
再来看效率最高的网络层多播,主机1可以仅通过1次报文传输,将文件分发到所有主机上。在整个流程中,仅由路由器将网络报文扩散到相邻的主机、路由器上,没有任何多余的动作。如同上述所说,网络层多播的使用有很多困难,这里列出它是为了方便与应用层多播作对比。
在上图的应用层多播中,文件传输分为两个阶段。首先,主机2、3直接从主机1中下载文件(参见绿色与红色线)。其次,当主机3完成下载后,主机4再从主机3上下载文件(参见蓝色线)。可见,相对于IP多播,应用层多播有以下3个缺点:
首先网络效率下降了不少,这由2个原因所致:
- 数据在网络中有冗余,比如主机1将数据重复发送了2次(参见红色、绿色线),主机3既接收了一次数据,也发送了一次数据;
- 虽然图中主机4从同一局域网中的主机3下载数据,但在复杂的互联网环境中,应用层很难掌握完整的路由器组网信息,主机4一旦跨网络从主机2上下载数据,这就增加了路由器A及网络链路的负载,效率进一步下降。
其次,由于传输路径变长了,文件传输的总完成时间也变长了。比如,主机4的总传输路径是:主机1 -> 路由器A -> 路由器B -> 主机3 -> 路由器B -> 主机4,既多出了主机3、路由器B这两个传输环节,而且进入主机3后,协议栈的处理深度也增加了。
最后,单次传输路径中引入了功能复杂的主机,相比仅由网络设备参与的IP多播,可靠性、稳定性也降低了。
说完缺点,我们再来看应用层多播的优点。
- 首先,它回避了IP多播的问题,无须改变现有组网环境,也不需要管理组播IP地址,立刻就可以应用在当下的生产环境中;
- 其次,在数以万计的大规模集群下,单一发布源很容易被流量打爆,进而导致分发流程停止,应用层多播可以避免这一问题;
- 再次,通过应用层节点的接力分发,整个传输带宽被大幅度提高了,分发速度有了数量级上的飞跃;
- 最后,如果分发集群跨越不同传输成本的网络(比如多个区域IDC构成的集群),在应用层也很容易控制分发策略,进而减少高成本网络的数据传输量,提升经济性。
所以,综合来说,**集群规模越大,应用层多播的优势也越大。**实际上十多年前,我们在使用BT、迅雷下载时,就已经接触到应用层多播协议了,接下来我们结合2个服务器端的案例,看看多播协议的实现与应用。
应用层多播协议是如何工作的?
其实,应用层多播主要是指一种P2P(Peer to Peer)网络传输思想,任何基于IP单播的通讯协议都可以拿来使用。比如针对于在分布式集群中分发软件安装包的场景,完全可以使用HTTP协议实现应用层的分发,阿里巴巴开源的Dragonfly蜻蜓就是这么做的。
蜻蜓拥有1个中心化的集群服务节点:SuperNode,其中既可以直接保存着源文件,也可以通过HTTP缓存加速第三方文件源(比如Docker仓库)。集群中的每个节点都要启动dfget进程(替代了传统的wget),它就像我们平时使用的迅雷,在下载文件的同时,也会将自己下载完成的文件传输给其他节点。其中,通过HTTP的Range文件分段下载规范,dfget就可以实现断点续传、多线程下载等功能,如下图所示:
各个dfget程序间通过SuperNode协调传输关系,这样绝大部分dfget程序并不需要从SuperNode节点下载文件。比如上图中的节点C,通过HTTP Range协议从节点A中下载了文件的第1块,同时并发地从节点B中下载了文件的第2块,最后再把这些Block块拼接为完整的文件。
这里你可能会想,这不就是一个P2P下载工具么?是的,但你站在集群运维的角度,这就是基于应用层多播协议的文件分发工具。当每个节点部署dfget服务后,新版本安装包发布时,就可以由SuperNode节点推送,经由各个dfget进程以多播的形式分发下去,此时性能会获得大幅度的提升。
上图是传统的wget单播与蜻蜓多播分发文件的性能对比图。我们可以看到,传统方式下,**分发客户端越多(Y轴)总分发时长(X轴)就越大,特别是1200个以上的并发节点下载文件时,会直接将文件源打爆。**而采用应用层多播方式后,下载时长要低得多,而且伴随着节点数的增加,下载时长也不会增长。
蜻蜓虽然传输效率很高,但SuperNode却是保存着全局信息的中心节点,一旦宕机就会造成系统不可用。我们再来看去中心化的Gossip流言协议是如何实现应用层多播的。
Gossip协议也叫epidemic传染病协议,工作原理如下图所示。在这个分布式网络中,并没有任何中心化节点,但只要第1个种子节点被感染为红色后,每个节点只需要感染其相邻的、有限的几个节点,最终就能快速感染网络中的所有节点(即仅保证最终一致性)。
当然,所谓的“感染”就是数据的传输,这一算法由1987年发布的《Epidemic algorithms for replicated database maintenance》论文提出,同时证明了算法的收敛概率。Cassandra数据库、Fabric区块链、Consul系统等许多去中心化的分布式系统,都使用Gossip协议管理集群中的节点状态。以Cassandra为例,每秒钟每个节点都会随机选择1到3个相邻节点,通过默认的7000端口传输包含节点状态的心跳信息,这样集群就可以快速发现宕机或者新增的节点。
小结
这一讲我们介绍了应用层的多播协议。
网络层的IP多播功能有限,对网络环境也有过多的要求,所以很难通过多播协议提升传输效率。基于IP单播协议(如TCP或者UDP),在应用代码层面实现分布式节点间的接力转发,就可以实现应用层的多播功能。
在分布式集群的文件分发场景中,阿里开源的Dragonfly蜻蜓可以将发布节点上的源文件,通过HTTP协议推送到集群中的每个节点上,其中每个节点在应用层都参与了多播流量分发的实现。当节点数到达千、万级时,蜻蜓仍然能保持较低的分发时延,避免发布节点被下行流量打爆。
在完全去中心化的分布式集群中,每个节点都没有准确的全局信息,此时可以使用Gossip流言协议,通过仅向有限的相邻节点发送消息,完成整个集群的数据同步,实现最终一致性。因此,Gossip协议常用于大规模分布集群中的节点状态同步。
思考题
最后,留给你一道讨论题。在5G完成设备层的组网后,类似华为NewIP这样的基础协议层也在做相应的重构,其中Multicast VPN协议就将现有IPv4无法在公网中推广的多播功能,在VPN逻辑链路层实现了。你对未来多播协议的发展又是如何看的?欢迎你在留言区与大家一起探讨。
感谢阅读,如果你觉得这节课让你了解到应用层的多播协议,而通过它可以大幅度提升分布式集群的网络传输效率的话,也欢迎你把今天的内容分享给你的朋友。