P2P技术如何拯救一家直播网站

Wesley13
• 阅读 1175

P2P技术如何拯救一家直播网站

众所周知运维成本是直播网站最大的成本组成,运维成本则主要体现在带宽,而伴随主播与用户对视频清晰度以及连麦的需求不断提升,直播带宽也在与日俱增。本文整理自学霸君音视频技术负责人袁荣喜在LiveVideoStackCon 2017上的分享,通过实践案例讲解了如何使用P2P技术将带宽和延迟降低到传统技术的1/3,并详细介绍了P2P分发算法的架构设计和技术实现细节。

演讲 / 袁荣喜

整理 / LiveVideoStack

大家好,我是来自学霸君的袁荣喜,我演讲的主题是《P2P技术是如何拯救一家直播网站的》,众所周知直播网站最大的成本就是运维成本,当然还会有一部分主播的成本,而运维成本的主要表现就在于带宽,从目前统计来看,一个直播网站的成本大概有30%来源于带宽。

一个直播网站的窘境

我的一个朋友是做直播平台的,每天大概有10万人观看,在经历了2016年的千播大战之后,他们升级了观看体验——主要是提高了分辨率和清晰度,但成本也因此提高到了原本的5倍,也就是假如原本是20G,现在每天要付出100G的带宽流量,这对于一个普通的平台来说成本是致命的。

基本情况

那么我们先来看下这家平台的具体情况:它是南方三线城市的直播平台,PC占有率大概有70%,移动端占有率在30%左右,码流也从320x240,20K升级到640x480,大概每秒的单路码流在800kbps左右,也就是100KB/S的样子 。因为它和YY类似,都属于聊天室形式的,也就说每一个观看端都会有上麦的需求,也因此必须要解决延迟的问题,如果延迟太大,在上麦的过程中和下麦的过程中有可能会产生信息不对等,由此丢失一部分信息,因此对于观看端延迟要求在两秒以内,而麦与麦之间的延迟要控制在500毫秒,这就对延迟有非常高的要求。

成本

前面提到平台观看人数能达到10万以上,它每天在边缘节点上就需要用83G来扛住边缘节点的分发,由于系统是分布式的,因此在边缘节点与边缘节点之间也需要做分发,这部分又会需要2G的BGP带宽流量,这个带宽很大。因此它需大概100台物理机来抗,对于私有云搭建的成本我并不是很了解,如果按照公有云来计算的话,每个月大概要支付百万以上的成本,这对于一个三线城市的小公司来说压力是巨大的,况且还有比较沉重的业务和寥寥无几的融资渠道。

存活的希望

那么平台想要继续存活,就需要将带宽成本降到现在的1/3,也就是只用30G就能解决问题。将产品迁移到CDN上是一个解决方法,毕竟各大云厂商目前的优惠力度还是比较大的,但他们在前期采用CDN做测试时发现会有两个问题:首先是延迟问题,在很多分享中也有提到CDN的延迟至少是3-5秒,有时候更大,尤其是在大规模直播下;而第二个问题则是每个观看端都会有上麦的需求,但连麦服务是需要额外付费的,综合计算使用CDN也无法降低成本,甚至还有增加。

那么我们考虑是否可以通过调整编解码来实现,大家都知道H.265从编码效果上来说可以减掉一半的成本,我们也在小规模内尝试了替换,不过发现存在CPU消耗的问题,因为观看端的设备比较多样,既有移动端、也有PC端,并且设备的性能参差不齐,在较差的机器上会频繁出现卡顿,根据统计大致有50%的用户无法接受这个方案。

那么既然是传输产生的高成本,是否可以对传输方式做优化——P2P技术,它早期源于音频分享和文件分享,并且是下一代CDN的主流技术。在做这样一个系统之前首先需要调研目前用户端上传的最大带宽,我们发现有50%以上用户的上传带宽在1.6mbs以上,平均来看大概可以做到640KB/S 码率的上传程度。前期调查后,我们确立了系统设计的三个目标:降成本、控延迟和保质量,也就是在保证用户体验下将成本降低1/3,在后期的小规模测试和大规模替换中的效果还是比较满意的。

流媒体P2P分发系统

网络架构

P2P技术如何拯救一家直播网站

接下来我们重点讲解这个分发系统的具体细节,首先上图是系统的架构图,大致分为四层:最上层是BGP——用来协调边缘节点与边缘节点之间的分发;第二层是边缘节点,它主要是用来分发媒体数据到观看端;第三层我们在客户端层面上做了一层超级节点,用来分摊大部分边缘节点的分发压力,这一层的主要目的就是为了节省带宽;第四层是普通节点,这主要是由于有些端可能是4G或者一些比较差的WiFi,它们可能没有上传的能力。那么在旁边还有一个小红圈,它表示推流的过程,因为业务中对上麦、连麦有需求,我们没有用连麦系统,而是采用了一种推流加连麦的方式来做,使用的是可靠UDP,也就是RUDP技术。

三部分网络

P2P技术如何拯救一家直播网站

整个网络分为三部分:一个是推流部分,就是我们要保证流是要推到边缘节点上;第二是边缘节点与边缘节点要做一个可靠、快速的分发,让所有数据尽量快到达Edge server,这样保证延迟比较小;第三部分是P2P,当数据到达Edge server上,我们要快速通过P2P网络分发到各个观看端进行播放。在这个系统中有个锚点,就是所有Edge sever都应该尽快拿到所有的视频数据和音频数据。

在具体介绍这三部分网络实现方式之前,我们先来看下流媒体中最重要的一部分——分发切片,也就说数据如何打包才能符合我们的要求和场景。最早我们采用HLS的方式,也就是一秒打一个分片,不过它会引来延迟的问题,从实际的测试中我们发现会有大于一秒的延迟,但如果分片太小了就又会引入其他问题。经过测试,我们最终采用一帧为一个分片,这样可以带来三个好处:首先是粒度小,每一帧大概在几十毫秒,这样我们可以尽量去优化这个延迟;第二点就是实现简单,因为每一个编解码都是基于帧的编解码,这样天然的就是一个分片模式;第三点是组织比较灵活,可以与播放buffer无缝接合。

推流

接下来我们具体讲解这三个网络是如何实现的。首先是推流,推流一般来说会用到RTMP或者说TCP的方式,但它会带来两个问题:在网络不好的情况下,因为每个端都需要上传和上麦的操作,这样会引来延迟问题,我们测试发现TCP最大的延迟有可能达到1.2秒,这是不可接受的;第二个就是在弱网环境下大量传输数据,它会产生TCP连接频繁的断开,这就会造成数据推不上去或者间断性的推上去,从而导致观看节点频繁卡顿。

P2P技术如何拯救一家直播网站

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

P2P技术如何拯救一家直播网站

由此我们在RUDP之上设计了一个多链路的传输(如上图):首先Edge server之间是直连的,同时有多个BGP server来做relay ,中间是无状态的,也就是即使某一条链路出现问题,其他几条链路还在并行传数据,这样就能保证尽量的可靠和可用。其次为了节省成本这里还有一个设计原则,Edge server之间尽量保证直连,不走BGP或者少量走BGP,这样就可以节省一大部分BGP流量,根据统计可以节省80%的成本。

P2P网络构建

要在P2P网络上做数据分发,就要构建一个鲁棒性的P2P网络——也就是动态可靠的P2P网络,构建这样一个网络需要分为三步:首先是连接——客户端之间要相互建立连接;第二是节点之间的评估;第三是节点分层。

  • P2P连接

对于连接,穿越是一个非常头疼的问题,而我们在最初的版本也是基于NAT的方式来做的,但同时引来一个问题——穿越里只有60%,也就是说有可能在某个防火墙或者NAT后面的节点拥有很好的上传资源,却没有得到利用。因此我们通过STUN协议做了一个多端口的猜测机制,通过这个机制可以将整个穿越率优化到80%。但依旧有一部分无法穿透,这是由于有些厂商会设置黑名单机制导致无法穿越,因此我们设计了云端协调穿越时机的机制,从而将穿越率优化到大概90%,也基本达到我们的预期。

P2P技术如何拯救一家直播网站

完成节点之间穿越,就可以做P2P通讯了。首先要建立心跳关系和心跳的状态交换,不过虽然从原则上来讲,一个节点跟所有的节点或者跟大部分节点能通讯是好的,但从实际效果来看并非如此,因为直播时有可能是一千个节点甚至更多节点,而一个节点不可能于这么多节点 频繁的做心跳或者信息交换,否则本身的带宽就会被这种探测包消耗掉,因此我们一般最多会选择40个节点,而这40个节点也并非是固定不变的,它会有优胜劣汰的机制,当有节点被淘汰时我们就会从没有穿越的节点中继续穿越,然后达到一个平衡,如此就会形成一种群居效应——好的节点会尽量聚集在一起。

  • 节点评估

在确定了邻居和通讯状态以及探测机制后,我们就要对整个通讯做评估。评估分为两部分:一个是评价邻居,主要通过丢包率、RTT、通信命中率以及流媒体传输的稳定性计算出一个亲和度分值;第二就是评估自己,主要通过CPU、带宽复用、网络类型等计算出一个load(负载)值,通过它我们就能知道本地节点跟其他节点大概处于什么位置,我们就能进行网络策略调节、通讯的QOS、节点区分以及网络收敛。我们早期的网络收敛是通过对照表的方式实现的——也就是经验值,但在网络高度动态时,会出现网络波动以及与邻居之间的通讯失效,因此我们采用一个简单的神经网络和一个收敛函数f(x) 来做参数的调整决策。

  • 节点分层

P2P技术如何拯救一家直播网站

完成节点评估后,我们需要根据评估结果做节点区分,也就是要解决超级节点和普通节点的问题。超级节点最重要的作用就是分摊Edge server的分发压力,同时还可能承担一部分网络节点管理工作。超级节点的产生方式有两种:一种是自我推荐,这种方式它需要得到Edge server的许可;第二种是Edge server自身的分发压力过于繁重,就会从质量比较好的普通节点中挑选一些比较稳定的成为超级节点。由于网络是动态的,有可能会出现衰减、分割、断开的情况,因此超级节点并非是永久的,当超级节点的网络出现衰减,评估函数f(x) 会作出反应降级为普通节点,这其实是一个高度动态的循环过程 。

P2P分发媒体数据

成功构建网络之后就是如何做数据分发,我们将它分为三步:先推、后拉、再补偿,我们下面逐一做详细介绍。

  • 三阶段——推

P2P技术如何拯救一家直播网站

我们假定已经选举好一个超级节点,那么边缘节点就会按照上图向下推送媒体数据到超级节点,超级节点再向下推给其他节点或超级节点,这个推送本身是树型结构,而P2P是图形结构,因此我们引入了预先订阅的机制。举例说明,假设某个节点播放到媒体包的第十秒,它就要开始订阅第二十秒到三十秒的包。那么订阅是如何完成的呢?超级节点在确定自己身份时会确定一个区域值,那么普通节点就会向所在区域的超级节点订阅(有可能会向多个超级节点订阅),对前面的例子而言,节点有可能会向超级节点A订阅一三五七九秒的包,向B订阅二四六八十秒的包。而超级节点也会做预先订阅,比如对于超级节点A而言,如果它自身负责一三五七九秒的包,那么直接向Edge server订阅;相反则需要向负责对应分片 的超级节点做订阅。

有了这样的订阅关系,Edge server和超级节点就会根据订阅的记忆信息向下推送。而这个推送路径一般最多达到两层,因为三层的拓扑太长,会引来延迟,同时路径过长,一旦某一个节点退出,受影响的节点太多。

  • 三阶段——拉

P2P技术如何拯救一家直播网站

我们前面提到整个协议是建立在UDP之上的,而在推送过程中UDP有可能会出现丢包,这时我们就需要向邻居拉取,那么如何拉取?首先我们通过gossip协议确定拉取的目标:也就是在单位时间内定时发送本地缓冲区有哪些包,把这些包通过gossip协议交换出去,邻居节点之间就会知道其他节点包的信息,假如出现丢包的情况,就可以通过gossip信息找到需要去拉取的节点,而拉取节点的选择是通过前面提到的亲和度分值尽量选取近的、通讯友好的节点,而这个拉取过程有可能会是多次的,如果出现拉取失败,则会在一个RTT周期 之后向其他节点拉取,它是一个循环的随机过程。

  • 三阶段——补偿

通过上述的手段我们就可以尽力把包拉取到本地,也可以减少对Edge server的依赖,但我们无法排除这样一种可能性,就是我的周围邻居都没有这个包,那么此时我们就只能向Edge server拉取,我们在前面有提到锚点的概念,Edge server应该具有大部分或者全部的流媒体信息。

P2P技术如何拯救一家直播网站

向Edge sever发起补偿的条件一般有两种:第一种是在整个P2P网络中稀缺的包;第二种是迫切需要播放的包。但这里面还存在一个风险,也就是频繁的发起补偿请求其实对Edge server是非常大的冲击,尤其是大量存在稀缺块的时候 ,因此我们需要限制Edge server单位时间内的补偿请求,但由于有了这种限制可能会导致某些节点补偿失败,这时它就会通过前面拉取的过程,通过gossip协议做查找拉取 ,而不是所有的都向Edge server拉取,这也是为了防止Edge server瞬间被补偿请求打死掉。

  • 三阶段播放buffer

当所有数据全部到了本地,本地会有一个播放缓冲区,包 括WebRTC都会有JitterBuffer这样的播放缓冲,我们也设计了一个Buffer,它与前面讲到的三阶段一一对应。

P2P技术如何拯救一家直播网站

第一个是推区间,也就是负责推流区域的缓冲,相当于一个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。

P2P技术如何拯救一家直播网站

经过算法的升级,我们最终实现了这样的效果:边缘节点带宽大致降到24G;BGP由于采用了多链路保障和直链的方式,大概降到原来的1/3-1/4的比例;因为带宽的降低,对物理服务器的依赖也就自然减少,目前服务器降到41台左右。这里值得一提的是,通过测试我们所有的端延迟大概在1秒左右,最大延迟在2秒左右,连麦延迟在200~800毫秒之间 ,与原先的情况相比,在保留固有功能和连麦系统等服务没受到影响的情况下,我们节省了大概1/3的带宽,基本达到了我们最初的要求,同时我们也还在不断优化这个网络模型,也欢迎感兴趣的小伙伴与我探讨。

以上是本次的分享,感谢大家。

WebRTCon 2018 8折报名

WebRTC天然不具备服务端能力,如何实现高性能、稳定的服务端能力成为绕不过的话题。我们特别开设了“WebRTC服务端开发”专题,并邀请本文分享者袁荣喜担任出品人,一同与网易云、苏宁文创、触宝电话等技术大咖分享接入网关服务、协议适配、服务稳定性和行业应用。

如果你拥有音视频领域独当一面的能力,欢迎申请成为讲师,分享你的实践和洞察,请联系 speaker@livevideostack.com。更多详情扫描下图二维码或点击阅读原文

P2P技术如何拯救一家直播网站

本文分享自微信公众号 - LiveVideoStack(livevideostack)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
PPDB:今晚老齐直播
【今晚老齐直播】今晚(本周三晚)20:0021:00小白开始“用”飞桨(https://www.oschina.net/action/visit/ad?id1185)由PPDE(飞桨(https://www.oschina.net/action/visit/ad?id1185)开发者专家计划)成员老齐,为深度学习小白指点迷津。
Stella981 Stella981
2年前
DOIS 2019 DevOps国际峰会北京站来袭~
DevOps国际峰会是国内唯一的国际性DevOps技术峰会,由OSCAR 联盟指导、DevOps时代社区与高效运维社区联合主办,共邀全球80余名顶级专家畅谈DevOps体系与方法、过程与实践、工具与技术。会议召开时间:2019070508:00至2019070618:00结束会议召开地点:北京主办单位:DevOps
Wesley13 Wesley13
2年前
P2P技术如何将实时视频直播带宽降低75%?
本文内容来自学霸君资深架构师袁荣喜的技术分享。1、前言实时视频直播经过去年的千播大战后已经成为互联网应用的标配技术,但直播平台的成本却一直居高不下,各个平台除了挖主播、挖网红以外,其背后高额的带宽费用也是他们最大的一块成本。现阶段直播技术在传输方面分为两块:CDN:负责流媒体的分发传输;连麦系统:负责解
Stella981 Stella981
2年前
Linux运维常见面试题之精华收录
Linux运维常见面试题之精华收录1、什么是运维?什么是游戏运维?1)运维是指大型组织已经建立好的网络软硬件的维护,就是要保证业务的上线与运作的正常,在他运转的过程中,对他进行维护,他集合了网络、系统、数据库、开发、安全、监控于一身的技术运维又包括很多种,有DBA运维、网站运维、虚
Stella981 Stella981
2年前
Android蓝牙连接汽车OBD设备
//设备连接public class BluetoothConnect implements Runnable {    private static final UUID CONNECT_UUID  UUID.fromString("0000110100001000800000805F9B34FB");
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这