现在比较流行的直播,经常会出现这样的情况: 用户打了一个弹幕上去,主播念出来的时候,弹幕已经飞出去了。二者时间是不匹配的。
这是我们的一个客户,两个主播连线互动,实时交互。试想,如果直播时延时高达几秒,像这样的双主播组合是没有办法进行交谈的。A说完之后,对方要等几秒才能听到,又过了几秒,A才能听到对方的回答。
这两个例子其实要说明实时互动直播和普通直播相比有本质的区别:延时。实时互动直播延时必须低达几百毫秒。
为什么是几百毫秒?为什么不是几秒也不是几毫秒?这是由人们日常交流习惯决定的。人的说话声音通过声波传播,如果两人相隔34米,那么延时就是100毫秒。基于这个范围,略长的延时,观众还能。基于互联网的音视频通信,音频通话延时标准在400毫秒以内,视频通话延时在800毫秒以内,这可以让通话双方无延时感知的。延时如果达到秒的数量级,那么通话双方就会有明显的等待。
互联网是基于电磁波或者通过光纤传播的。光绕地球一圈,耗时300毫秒,这是无法逾越的物理定律延时。有人号称可以做到0延时,他们估计用上了量子通信。在实际互联网应用中,网络条件并不理想,互联网信号绕地球一圈的延时必然大于300毫秒。这就给实时互动直播,带来了巨大的挑战。
实时互动直播的挑战
第一,互联网的骨干网上路由器的部署,不是直线点到点,而是中间要经过很多路由器的跳数,实际上是在走“弯路”。所以,互联网传输没有办法绕地球一圈正好300毫秒,最好的情况也需要要近400毫秒。
第二,公共互联网上,路由器其实经常出现故障。比如,在晚高峰的时候,网络会比较慢。这是因为部分路由器可能过载。因为路由器有最大的处理能力上限,一旦超过上限,就不能处理,会造成丢包、拥塞。
第三,无线网络相对有线网络,可靠性较低。无线网络普及度越来越高,,越来越多的手机、笔记本连接无线网。但是无线网络相对有线网络没有那么可靠,同时也会引入信号污染。信号覆盖不到的地方,效果较差。
第四,高并发挑战。首先需要普及一个概念:并发和在线是有区别的。当今的移动互联网,大家都在讲千万级。当我们谈及海量用户架构这个话题时,似乎如果不说到上亿这个量级,是落后了。但是实际上,前面这些说法都混淆概念了,它们都在说“在线”,而不是“并发”。以下图为例:
左边是QQ在线好友列表,图中可以看到很多好友展现,其实没有交互,使用者不会有压力。右边是一个框同时和很多人聊天,使用者会感受到巨大压力。同样的,对于直播服务而已,如果用户只是在线,很少会跟服务器有交流,最多偶尔发一个心跳包。
用户在线时,如果参与了“看”“说”,这就是并发。直播的并发峰值具有突发性,往往跟主播的活动密切相关。比如,主播会跟粉丝约定直播时间,到了约好的时间,粉丝就会在短时间大量涌入一个直播频道。观众慢慢进入频道,服务器没有压力,但如果瞬间涌入,后台的压力非常大。
本文,将重点介绍互动直播的可用性问题。电信业务的可用性标准是四个九,我们期望做到五个九。双十一时,支付宝的处理能力非常强,百度百科上提供的数据显示,支付宝当天处理了96%订单。但是,我们对自己的互动直播有更高的要求,期望做到99.999%。
实时互动直播要保证高可用性,有巨大的难度,原因如下:
实时很难。互联网基础设施不是为实时通信设计的。
覆盖很难。机房找点,互联互通。对通信云来说,覆盖不好会影响到可用性。
高并发很难。不能看着看着就不动了,没声了。
突发性很难。系统容量要高,还要防止雪崩。
这些挑战我们在做整个服务的时候,都需要全面考虑。
直播架构的演进
1、CDN直播架构
这是当前流行的直播架构,左下角是一个主播,主播通过手机或电脑等设备,把自己的视频流上传到服务器,接入目前流行的CDN服务,通过CDN服务进行网络分发,分发到各地的用户。所有用户都可以看到主播的表演。
2、单服务器实时互动直播架构
实时互动直播,不能使用CDN方案,因为CDN方案性质决定了延时达不到实时的要求。下图是我们认为可以实现实时互动的架构。主播把自己的视频流上传到服务器,通过这台服务器分发给其他用户,再采用合适的传输协议,延时可以做到很小。从主播到服务器再到观众的延时,加上编解码和抖动的延时,可以做控制在几百毫秒以内。
这个架构很简单,但有一个缺点,没有考虑覆盖不同地用户的问题。并且一台服务器支撑不了大规模用户。这台服务器如果宕机,或者服务器机房出故障,整个传输都会受到影响。这必然达不到高可用架构的标准。
3、分布式实时互动直播架构
主播的视频流上传到一个接入服务器,这个服务器会把这个视频流分发到我们部署在世界各地的服务器。然后这些服务器接入本地的用户,把视频传下去。
在这个架构里面,首先可以解决的是覆盖问题,部署在世界各地的服务器,可以让用户可以快速就近接入。整个视频流通过我们在互联网上做的分布式传输算法,把它实时的传输到世界各地的机房。其次,可以避免机房甚至骨干网故障,对传输造成的影响。
如何实现高可用性
可用性可以分为两个部分:接入可用性和使用可用性。你在使用服务的时候,能够接得进去,能够听得到,这是接入可用性。举个例子,打电话的时候,有时会出现你所呼叫的用户无法接通,因为用户的手机没有接入电信服务,这就是接入可用性问题。在通话的时候,听不到对方说话了,使用中掉线了,这就是使用可用性。
为了实时监测可用性,我们做了两方面的监测:
1、主动监测
服务可用性不能依靠用户数据反馈或者用户主动上报,这样你永远是最后一个知道的。况且初期用户量小怎么办?因此,我们需要自己给出我们的服务有多可靠。为此,我们研发主动监测系统来监测整个服务。端到端监测,接入有没有问题,在使用的过程中会不会出问题。
2、被动监测
用户在使用我们的服务的时候,我们会收集用户接入服务的整个过程,多长时间可以接入,接入时经过了几次请求,使用中有没有掉线,中间有没有声音终端或卡顿。我们会收集这些数据,据此了解服务的可用性。
有了监测数据,那么就可以据此来不断改进我们的服务,解决前面所说的挑战。
1、覆盖问题
在中国做互联网的人应该都有一个感受,联通跨电信,用户之间是难以交互的。早期的QQ传文件没有做中转,如果联通和电信的用户要互相传文件,速度非常慢,甚至会中断。玩网游的用户,也会遇到有电信专区、网通专区。下图是一个简单的测试,当跨运营商的时候,发一个包,可以看到里面有很多丢包。这个数字是RTT,这个测试结果可以看出,最小是62毫秒,最大是840毫秒。
不但中国有网络互通的问题,国外也有。很多人以为发达国家,比如美国、日本,互联网的基础设施较好,所以不会有互联互通的问题。但是,在我们做实际测试时,美国的互联网也存在互联互通的问题,只是状况比中国好一些。
上图,展示了一个一个阿尔及利亚用户的网络状况。他接入的是国家电信的服务商,从骨干网接入阿尔及利亚电信有很多线路,最下面的线路意大利电信是最直接的。如果不走意大利电信,那么中间就必须经过很多运营商跳转。在这种情况下,要保证用户有做最快的传输,就要保证传输走意大利电信。这必须依靠覆盖来解决。
如何解决覆盖问题?
首先,部署大量边缘服务器。边缘服务器的地理位置越接近用户越好,二者的线路越接近约好,同一个SP最好。比如中国国内,我们会有大量电信、联通、移动服务器。当我们发现一个接入的用户是电信时,我们会找电信线路,如果是联通的会找联通线路。再看回上一个图,如果遇到阿尔及利亚的用户要怎么办?在现在的服务里面我们就要找一个意大利电信接入,而不是随便找欧洲的机房。必须部署很多边缘服务器才能做到这一点。
其次,要有分配服务。有边缘服务器之后,用户还是无法接入边缘服务器,因为他不知道接哪个。因此,必须有配套算法,根据用户的SP,找到和他最匹配的边缘服务器,来进行接入分配。
2、跨地域问题
我们在全中国有好几十个机房,其中有很多电信的机房,不同的电信用户来使用我们的服务,应该给他哪个电信机房呢?如果把北京电信用户接到广州的电信机房,虽然大多数情况下丢包不会很高,但延时会比较大。为此,我们设计了就近接入算法,使用我们服务的每个用户,都会接入到最靠近他,且线路最匹配的服务器。
当我们就近按SP接入时,遇到了一个新问题:假如一个香港用户,接入的是香港机房,想看北京联通用户的表演,那么这个香港用户怎么看到北京用户的表演呢?我们就需要有一个分布式传输的架构和算法,来把北京的流量传到香港。
3、DNS解析问题
今天无线互联网非常普及,使用无线网时,有一个问题比有线网更严重:DNS解析。用户接入时,第一步是通过域名解析,解析到最近的服务器。但是,做DNS解析时,无线网络的信号会存在污染,导致DNS解析失败。为此,我们优先使用解析,解析不到再用静态IP配置。
4、骨干网故障问题
我们发现在骨干网上,很多默认的骨干网路由经常出问题,同时有一些骨干网部分是不会拥堵的。基于这样的发现,我们做了自己的路由网络。
在默认路由之外,我们会额外部署路由机房。比如,从上海到洛杉矶,假设默认线路到晚上高峰期会比较拥堵,同时我们发现从上海经过广州再经过香港再到洛杉矶,这条线路不会拥堵。那么,我们就会部署这样一条路由线路,然后做自动的适配。
如果骨干网上出故障了,我们通过路由的方式构建Overlay应对。首先,我们的应用会先连接到分配服务,分配服务会给出一批可接入的机房,当接入的机房坏了,就立即切换到下一个可用机房,如果发现还是坏了,则再次接入到分配服务,继续寻找当前可用服务器。
5、蜂拥
蜂拥是实时互动直播里面特别突出的现象,短时间内大量用户进入频道或者使用服务。蜂拥对整个后台的冲击力非常强。大多数的互联网的后台服务器每秒接入大概千的量级,但是对于蜂拥而来的用户,处理量远远不够。这时候就会遇到一个问题,后台处理响应速度越来越慢,很多用户的请求会超时。超时之后就会进入更多的请求,请求就会像滚雪球一样越来越大,导致整个后台系统不能响应,整个系统就会产生雪崩,这叫雪崩效应。
如何防止雪崩效应
1)要把性能上限提高。通常来说我们的性能上限会达到峰值处理能力10倍以上。性能上限提高要做分配服务性能扩展,我们的做法一般是水平扩展,因为垂直扩展比较困难。
2)应用里面做自动的重复请求,它会不断累计请求量,我们要做退避的策略。
3)保证整个接入服务本身的可用性问题,处理方法很简单,多点备份,然后做并发的请求。我们有很多分配的服务器,们的应用接入的时候会同时从几个点请求分配,分配到一批边缘服务器之后,会同时连接几个边缘服务器,哪个先响应就处理哪个。
本文整理自声网Agora.io 1号架构师李伟,在ArchSummit深圳2016 全球架构师峰会 的演讲。
【李伟】
2006年-2008年,在PP live工作的时候研发了PP live(已更名PPTV),当时最高有接近150万人在线。
2008年到2010年,在新浪负责新浪视频的研发,2008年的欧冠直播,40万人在线。
2010年到2013年在YY工作,主要负责YY的架构,最高在线是超过一千万,最大的单人频道达150万左右。
2013年,加入声网,负责声网音视频的系统架构。