本文整理自学霸君音视频技术负责人愤怒的宝贝在LiveVideoStackCon2017上的分享,通过实践案例讲解了如何使用P2P技术将带宽和延迟降低到传统技术的13,并详细介绍了P
本文整理了LiveVideoStackCon 2017中自学霸君音视频技术负责人愤怒的宝贝分享,通过实践实例说明了如何使用P2P技术将带宽和延迟降低到传统技术的1/3,以及P2P分发算法的体系结构设计和技术实现
P2P技术如何拯救直播网站IT大咖内容的来源:本文由IT大咖(WeChat_ID:itdakashuo )为现场视频堆栈微信公众号(ID: livevideostack ) 好的句子请多支持! 感谢您的阅读~
众所周知,运输成本是实时站点的最大成本配置,运输成本主要体现在带宽上。 随着播音员和用户对视频清晰度和连麦的需求不断增长,现场带宽也在日益增长。
本文整理了LiveVideoStackCon 2017中自学霸君音视频技术负责人愤怒的宝贝分享,通过实践实例说明了如何使用P2P技术将带宽和延迟降低到传统技术的1/3,以及P2P分发算法的体系结构设计和技术实现
你好,我是学霸君的愤怒宝贝。 我演讲的主题是《P2P技术是如何拯救一家直播网站的》。 众所周知,直播网站最大的成本是运输成本。 当然播音员的成本也有一部分,但运输成本的主要表现是带宽。 从目前的统计数据来看,实时站点约30%的成本来自带宽。
对某直播网站的困境感到高兴的小虾在做直播平台,每天约有10万人观看。 在经历了2016年的千播战争之后,他们升级了观看体验,——主要提高了分辨率和分辨率,但成本也上升了原来的5倍。 也就是说,如果本来是20G,现在每天要支付100G的带宽流量,这对普通平台是致命的。 基本情况是,先看看这个平台的具体情况。
南方三线城市实时发布平台,PC占比约70%,移动端占比30%左右,码流也从320x240、20k升级到640x480,每秒800kbps左右,即100KB/S秒
因为和YY很像,所以是聊天室形式。 **也就是说,所有观众都有上麦的需求,因此必须解决延迟的问题。 **如果延迟太大,上麦过程和下麦过程中可能信息有误。 因此,会失去一部分信息。因此对于观看端延迟要求在两秒以内,而麦与麦之间的延迟要控制在500毫秒,这就对延迟有非常高的要求。成本上述平台的观众人数可达10万人以上。 每天必须在边缘节点上以83G承担边缘节点的分发。 **由于系统是分布式的,因此也需要在边缘节点和边缘节点之间分发。 ** 这部分又会需要2G的BGP带宽流量,这个带宽很大。因此,需要约100台物理机进行对抗。 我对私有云的构建成本不太清楚。 **以公共云计算,每月要支付约100万美元的生存希望那么多平台要想继续生存下去,带宽成本只需要目前的1/3,即30G就能解决问题。 将产品转移到CDN是一种解决方法,虽然各大云厂商目前的优惠力度比较大,但在**前期采用CDN进行测试时,发现存在两个问题。 首先是延迟问题,很多共享也指出CDN的延迟至少为3-5秒,**更大,特别是在大规模的直播中; 第二个问题是所有观众都有上麦的需求。但连麦服务是需要额外付费的,综合计算使用CDN也无法降低成本,甚至还有增加。
考虑是否可以通过调整编解码器来实现。 众所周知,H.265从编码效果上可以减少一半的成本。 我们也尝试了小规模的置换,但发现存在CPU消耗的问题。 观看设备种类繁多,有移动端,也有个人电脑端,设备性能参差不齐,不良设备经常出现纸箱,据统计,约50%的用户无法接受该方案。
既然新一代CDN的主流技术是传输带来的高成本,那么能否优化传输方式? 它最初源于音频共享和文件共享,是新一代CDN的主流技术。 在制作这样的系统之前,首先需要调查当前客户端上传的最大带宽,发现50%以上的用户的上传带宽在1.6mbs以上,平均可以进行约640KB/S的编码率的上传程度。 在前期调研后,我们确立了系统设计的三个目标:降成本、控延迟和保质量,也就是在保证用户体验下将成本降低1/3,在后期的小规模测试和大规模替换中的效果还是比较满意的。流媒体P2P分发系统网络体系结构
接下来,重点说明该分发系统的具体细节。 首先,上图是系统的体系结构图,大致分为四个层次。最上层是BGP——用来协调边缘节点与边缘节点之间的分发第2层主要是用于向观看者分发媒体数据的边缘节点。第三层我们在客户端层面上做了一层超级节点,用来分摊大部分边缘节点的分发压力,该层的主要目的是节约带宽; 第4层是普通节点。 这主要是因为一些端点可能是4G或较差的WiFi,并且可能没有上传的能力。 那么,旁边就是xhdwt圈。 这表示按流程的过程。 业务中对上麦、连麦有需求,请访问我们没有用连麦系统,而是采用了一种推流加连麦的方式来做,使用的是可靠UDP,也就是RUDP技术。
ng> 三部分网络
整个网络分为三部分:一个是推流部分,就是我们要保证流是要推到边缘节点上;
第二是边缘节点与边缘节点要做一个可靠、快速的分发,让所有数据尽量快到达Edge server,这样保证延迟比较小;第三部分是P2P,
当数据到达Edge server上,我们要快速通过P2P网络分发到各个观看端进行播放。在这个系统中有个锚点,就是所有Edge sever都应该尽快拿到所有的视频数据和音频数据。 流媒体中最重要的一部分——分发切片 在具体介绍这三部分网络实现方式之前,我们先来看下流媒体中最重要的一部分——分发切片,也就说数据如何打包才能符合我们的要求和场景。最早我们采用HLS的方式,也就是
一秒打一个分片,不过它会引来延迟的问题,从实际的测试中我们发现会有大于一秒的延迟,但如果分片太小了就又会引入其他问题。 最终采用一帧为一个分片 经过测试,我们
最终采用一帧为一个分片,这样可以带来三个好处:首先是粒度小,每一帧大概在几十毫秒,这样我们可以尽量去优化这个延迟;第二点就是实现简单,因为每一个编解码都是基于帧的编解码,这样天然的就是一个分片模式;第三点是组织比较灵活,
可以与播放buffer无缝接合。 推流 接下来我们具体讲解这三个网络是如何实现的。首先是推流,推流一般来说会用到RTMP或者说TCP的方式,但它会带来两个问题:
在网络不好的情况下,因为每个端都需要上传和上麦的操作,这样会引来延迟问题,我们测试发现TCP最大的延迟有可能达到1.2秒,这是不可接受的;
第二个就是在弱网环境下大量传输数据,它会产生TCP连接频繁的断开,这就会造成数据推不上去或者间断性的推上去,从而导致观看节点频繁卡顿。 UDP可以很好的解决延迟和连接的问题,但由于它的不可靠,会产生丢包问题,
因此我们借助了WebRTC的GCC 原理,在UDP之上设计了一层可靠,保证数据可以尽快、尽好的传到Edge server上。上图是它的原理,它通过
一系列并发的发包,最后再通过确认机制来回馈要重传的包或者说什么时候重传包。 单路径RUDP 数据到了Edge server上之后就要把数据快速的传输到其他Edge server,我们最初的设计和CDN一样——通过BGP server单线的中转,也就是Edge server将数据传到BGP server,再由BGP server传输到其他Edge server上,这种做法最大的好处在于实现简单,并且链路查找问题比较明确。但同时它也存在两个问题:首先就是成本比较高,
因为BGP的成本是整个Edge server边缘节点带宽成本 的10倍;第二点因为它是建立在私有云上,**而私有云每个机房都有防火墙,而当网站频繁受到攻击时就有可能变换防火墙策略,这样就有可能导致某条链路不通或者到BGP不通,**由此就会影响Edge server无法接收数据包,从而导致观看节点卡顿。 多路径RUDP
由此我们在RUDP之上设计了一个多链路的传输(如上图):
首先Edge server之间是直连的,同时有多个BGP server来做relay ,中间是无状态的,也就是即使某一条链路出现问题,其他几条链路还在并行传数据,这样就能保证尽量的可靠和可用。其次为了节省成本这里还有一个设计原则,**Edge server之间尽量保证直连,不走BGP或者少量走BGP,**这样就可以节省一大部分BGP流量,根据统计可以节省80%的成本。 P2P网络构建 P2P连接 对于连接,穿越是一个非常头疼的问题,而我们在最初的版本也是基于NAT的方式来做的,但同时引来一个问题——穿越里只有60%,也就是说有可能在某个防火墙或者NAT后面的节点拥有很好的上传资源,却没有得到利用。因此我们通过STUN协议做了一个
多端口的猜测机制,通过这个机制可以将整个穿越率优化到80%。但依旧有一部分无法穿透,这是由于有些厂商会设置黑名单机制导致无法穿越,因此我们设计了**云端协调穿越时机的机制,**从而将穿越率优化到大概90%,也基本达到我们的预期。 P2P通讯 完成节点之间穿越,就可以做P2P通讯了。首先要建立心跳关系和心跳的状态交换,不过虽然从原则上来讲,一个节点跟所有的节点或者跟大部分节点能通讯是好的,但从实际效果来看并非如此,因为直播时有可能是一千个节点甚至更多节点,
而一个节点不可能于这么多节点 频繁的做心跳或者信息交换,否则本身的带宽就会被这种探测包消耗掉,因此我们一般最多会选择40个节点,而这40个节点也并非是固定不变的,它会有优胜劣汰的机制,当有节点被淘汰时我们就会从没有穿越的节点中继续穿越,然后达到一个平衡,如此就会形成一种群居效应——好的节点会尽量聚集在一起。 节点评估 在确定了邻居和通讯状态以及探测机制后,我们就要对整个通讯做评估。评估分为两部分:一个是评价邻居,主要通过丢包率、RTT、通信命中率以及流媒体传输的稳定性计算出一个亲和度分值;第二就是评估自己,主要通过CPU、带宽复用、网络类型等计算出一个load(负载)值,
通过它我们就能知道本地节点跟其他节点大概处于什么位置,我们就能进行网络策略调节、通讯的QOS、节点区分以及网络收敛。我们早期的网络收敛是通过对照表的方式实现的——也就是经验值,但在网络高度动态时,会出现网络波动以及与邻居之间的通讯失效,
因此我们采用一个简单的神经网络和一个收敛函数f(x) 来做参数的调整决策。 节点分层
根据评估结果做节点区分 完成节点评估后,我们需要根据评估结果做节点区分,也就是要解决超级节点和普通节点的问题。
超级节点最重要的作用就是分摊Edge server的分发压力,同时还可能承担一部分网络节点管理工作。超级节点的产生方式有两种:一种是自我推荐,这种方式它需要得到Edge server的许可;第二种是Edge server自身的分发压力过于繁重,**就会从质量比较好的普通节点中挑选一些比较稳定的成为超级节点。**由于网络是动态的,有可能会出现衰减、分割、断开的情况,因此超级节点并非是永久的,当超级节点的网络出现衰减,
评估函数f(x) 会作出反应降级为普通节点,这其实是一个高度动态的循环过程 。 P2P分发媒体数据 成功构建网络之后就是如何做数据分发,我们将它分为三步:先推、后拉、再补偿,我们下面逐一做详细介绍。
1 三阶段——推
我们假定已经选举好一个超级节点,那
么边缘节点就会按照上图向下推送媒体数据到超级节点,
超级节点再向下推给其他节点或超级节点,这个推送本身是
树型结构,而P2P是图形结构,因此我们引入了
预先订阅的机制。 假设某个节点播放到媒体包的第十秒,它就要开始订阅第二十秒到三十秒的包。那么订阅是如何完成的呢?
举例说明,假设某个节点播放到媒体包的第十秒,它就要开始订阅第二十秒到三十秒的包。
那么订阅是如何完成的呢?超级节点在确定自己身份时会确定一个区域值,那么普通节点就会向所在区域的超级节点订阅(有可能会向多个超级节点订阅),对前面的例子而言,节点有可能会向超级节点A订阅一三五七九秒的包,向B订阅二四六八十秒的包。
而超级节点也会做预先订阅,比如对于超级节点A而言,如果它自身负责一三五七九秒的包,那么直接向Edge server订阅;
相反则需要向负责对应分片 的超级节点做订阅。
有了这样的订阅关系,Edge server和超级节点就会根据订阅的记忆信息向下推送。而这个推送路径一般最多达到两层,因为三层的拓扑太长,会引来延迟,同时路径过长,一旦某一个节点退出,受影响的节点太多。
2 三阶段——拉
我们前面提到整个协议是建立在UDP之上的,而在
推送过程中UDP有可能会出现丢包,这时我们就需要向邻居拉取,那么如何拉取?首先我们
通过gossip协议确定拉取的目标:**也就是在单位时间内定时发送本地缓冲区有哪些包,**把这些包通过gossip协议交换出去,邻居节点之间就会知道其他节点包的信息,假如出现丢包的情况,就可以通过gossip信息找到需要去拉取的节点,而拉取节点的选择是通过前面提到的亲和度分值尽量选取近的、通讯友好的节点,而这个拉取过程有可能会是多次的,如果出现拉取失败,
则会在一个RTT周期 之后向其他节点拉取,它是一个循环的随机过程。
3 三阶段——补偿
通过上述的手段我们就可以尽力把包拉取到本地,也可以减少对Edge server的依赖,但我们无法排除这样一种可能性,就是我的wydsg都没有这个包,那么此时我们就
只能向Edge server拉取,我们在前面有提到
锚点的概念,
Edge server应该具有大部分或者全部的流媒体信息。 向Edge sever发起补偿的条件一般有两种:第一种是在整个P2P网络中稀缺的包;第二种是迫切需要播放的包。但这里面还存在一个风险,也就是频繁的发起补偿请求其实对Edge server是非常大的冲击,尤其是大量存在稀缺块的时候 ,因此我们需要限制Edge server单位时间内的补偿请求,但由于有了这种限制可能会导致某些节点补偿失败,这时它就会通过前面拉取的过程,
通过gossip协议做查找拉取 ,而不是所有的都向Edge server拉取,这也是为了防止Edge server瞬间被补偿请求打死掉。
4 三阶段播放buffer
当所有数据全部到了本地,本地会有一个播放缓冲区,包 括WebRTC都会有JitterBuffer这样的播放缓冲,我们也设计了一个Buffer,它与前面讲到的三阶段一一对应。
第一个是推区间,也就是负责推流区域的缓冲,相当于一个Push的JitterBuffer,这里设置的400ms缓冲主要是为了防止过度拉取,因为推送的流是不规则的,UDP会出现抖动、丢包、延迟,**同时P2P多路径传输之间本身的问题会引来抖动,**这个buffer就是为了防止太快进行拉取用的 。第二个是拉区间,在这个区间我们一般会向邻居拉取三次,这之间的缓冲也就是与邻居之间的3个RTT来回。如果三次没拉到,就会进入补偿区,补偿区就会向服务器拉取4次,如果没有拉取到数据则会返回拉区间。
经过这样的循环过程最终包被播放,对于已经播放的包是否要删除呢?我们知道P2P是对等系统,可能别人缺少你已经播放的包,向你拉取,但你播放结束后就直接删除了,这就导致没有命中,这种现象肯定不是我们希望看到的,因此我们将已经播放的分片放到缓冲区中保留3秒,尽量使得拉取请求命中。以上就是整个分发过程。
最终效果
下图是Edge server的对比数据,我们在Edge server上做了一个开关——将它等分为开启P2P分发和不开启P2P分发,对同一个Edge sever以一天为单位收集数据:每5分钟采集一次当时每秒出去的带宽,图中红色的线表示没有开启P2P,也就是完全使用Edge server来中转,蓝色的线表示开启P2P。图中我们可以看到在高峰期,开启P2P从Edge server输出的流量大概不到100mb/s ,而未开启P2P的则是达到了将近480mb/s ,也就是在 Edge server上可以节省到原来的1/4。
经过算法的升级,我们最终实现了这样的效果:边缘节点带宽大致降到24G;
BGP由于采用了多链路保障和直链的方式,大概降到原来的1/3-1/4的比例;因为带宽的降低,对物理服务器的依赖也就自然减少,目前服务器降到41台左右。这里值得一提的是,通过测试我们所有的端延迟大概在1秒左右,最大延迟在2秒左右,连麦延迟在200~800毫秒之间 ,与原先的情况相比,在保留固有功能和连麦系统等服务没受到影响的情况下,我们节省了大概1/3的带宽,基本达到了我们最初的要求,同时我们也还在不断优化这个网络模型,也欢迎感兴趣的小伙伴与我探讨。
以上是本次的分享,感谢大家。
编者:IT大咖说,转载请标明版权和出处