ITBear旗下自媒体矩阵:

听云APMCon: 直播云性能优化实践

   时间:2016-08-26 10:57:58 来源:论坛 编辑:星辉 发表评论无障碍通道

中国应用性能管理行业盛宴——2016中国应用性能管理大会(简称APMCon 2016)于8月18日至19日在北京新云南皇冠假日酒店隆重召开。APMCon由听云、极客邦和InfoQ联合主办的作为国内APM领域最具影响力的技术大会,首次举办的APMCon以“驱动应用架构优化与创新”为主题,致力于推动APM在国内的成长与发展。

七牛云首席布道师何李石于基于云架构的性能优化专场发表了题为《七牛直播云性能优化实践》的演讲,现场解读了七牛直播云服务在各个环节性能监控和优化的实践,包括服务端实时流网络性能优化,客户端编码解码效率和首开时间优化等内容。

以下为演讲实录:

大家下午好!我是来自七牛的何李石,今天跟大家分享一下直播相关的内容。我们七牛一开始是做存储的,后来基于存储我们做了分发,因为我们要让客户的文件能够快速的上传和下载。2014年年底我们接了一些监控摄像头的服务,我们发现直播是未来一个比较常用的场景,然后我们就做了直播云。从2014年年底到今年6月份,我们接到很多直播的客户,经过这些验证,在6月30号我们正式发布了直播云。因为今天是APM大会,我主要跟大家分享一下我们在性能方面是怎么去做优化的。实际上直播对我们来说是一个完整的解决方案,所以优化应该是包括整个环节,包括推流端、网络以及播放端。

我们先来看一下业务模型是什么样?最下面有一个推流端,中间是我们的实时流网络,可以理解成CDN,但他的网络架构和CDN不太一样,最右边是播放端,大家如果经常看直播接触最多的是右边这块。中间是我们的实时流网络,这些代表节点,这个线路代表一个流的流向,有调度服务节点,这样子的基本业务模型构成了直播解决方案。我们做的事情包括所有这些,包括推流端推出去,到网络的分发以及播放端。今天我分享的是性能相关的东西,性能实际上涉及到整个链路,包括推流端的性能、网络性能、播放端的性能都会涉及到。


我们再来看一下它的内核,对于我们的客户来说,我们提供的三个端的SDK都有,推流端SDK、实时流网络SDK还有播放端,播放端就是跟解码和播放相关的SDK。

这里我们简单讲一下七牛相关的业务,一开始我们有一个存储系统,为了加速用户的分发以及上传下载我们做了内容分发网络,这是存储和CDN相关的东西,后面我们做了通用的计算平台,以及基于对象存储上面做了数据处理平台,以及现在做的大数据平台。因为会有很多的图片或音视频,在这个基础上做了一些深度学习,相当于对大数据进行处理的平台。然后我们看直播,直播实际上是一个解决方案,它包含推流端SDK、播放端SDK以及直播云,会对直播流进行处理,因为我们知道直播就是一个分发通道,对上面的内容进行处理,这些处理包括录制回放、转码的处理还有内容识别。内容识别我们最常见的就是加速,加速是网络的主要功能。然后基于这个可能还需要做一些运营相关的东西,比如说计费之类的。

对于我们的客户或者直播的App开发者来说使用方式是这样的,一般会有一个自己的App Server,这三块SDK,推流端SDK、云的SDK还有播放端的SDK这是我们刚才介绍的内容。App里面除了Server端和DB之外,还可能需要实现跟业务相关的东西,比如说弹幕、道具、点赞等等,这些目前都是我们来实现的。

简单介绍完七牛的直播业务模型之后,我们再来看一下我们目前做一个直播的产品遇到的挑战以及关键指标有哪些。

对于终端用户或者我们的开发者来说,他有几个关键性的指标。首开时间,我们希望比如说你用映客的话就是一点就能开,最好控制在1秒以内。然后是累计延迟,比如我在这边讲的时候,有人在那边看,他整个延迟时间不能超过3秒,最好是在1秒以内。昨天有人分享做1秒以内的延时,这也是可以做到的,今天还看到做到500毫秒以内的延迟,我待会儿会讲为什么我们不是这么做的。另外就是低卡顿率,你要让客户非常流畅地观看你的视频,既使是码率和分辨率不是太多。还有就是高可用,我们目前都是用竖状CDN做到的,你的节点可以做到冗余,我们这边的网络会不太一样,一会会介绍。然后就是低成本,对于我们一个新的公司或者创业公司来说要自己做直播的话,他的成本实际上是非常重要的,我们不可能一下子就建一个非常大的CDN网络去做这方面的事情,但是我们可以用一种更加低成本的方式去做到同样高可靠、高可用以及性能、速度也能达到足够好。

再来看一下我们的挑战是什么?一个是实时传输,我们知道所谓的直播实时性非常重要,主要体现在传输协议和网络方面。另外就是他有海量的终端用户,比如说上次运动员可能映客会说有2000万用户,瞬间来了非常多的用户,就会造成一种惊群效应,什么意思呢?就是说你这个节点里瞬间来了非常非常多的用户,可能导致你整个节点的所有用户都拥堵了。还有一个是实时转存,我们知道北京这边有一个监管要求,要求把实时直播内容能够存储下来,保存一定的时间,这是需要有海量存储支持的。然后是多屏多终端适配,这就更加明显,比如我们每个人手机都不太一样,或者电脑,对一个云平台来说他的要求就是能实时转码,在编码和解码方面做到比较好的兼容性。

我们先来看一下推流端,输出之前需要经过采集、处理、编码的过程。这里面有一系列的Buffer,这些Buffer都是为了做好每个环节的控制。比如说采样的控制,我们有一个视频或者音频的采样率需要控制,如果采样率太高的话可以采到比较清晰的音视频,但是他的内容太多了,或者他对于硬件的要求很高。在采样完成之后到处理环节,处理环节就是我们经常说的一些滤镜、美颜、水印,我们一般会用GPU做处理。再到编码环节,编码在推出之前有一个Buffer控制编码的效率,比如我在收到网络反馈之前可能需要降码、推流,降码就是通过网络的带宽或者说网络的质量反馈回来之后,可以实时调整编码的码率。还有一个是推流,昨天听云的人分享了一个客户端的劫持,劫持在中国是非常严重的,即使没有劫持,我们也可能对这个解析没法控制,所以我们需要在智能网络方面做一些特殊的调度,配合服务端去做。还有热网情况下怎么去优化它的推流的效率,我可能先丢失一些帧做推流。

除了这些编码相关环节的优化之外,我们可能还有一个非常重要的模块,就是QoS,质量的实时上报模块。我们做到的是结合自己的模块和第三方的,比如听云的质量调优和报警模块做这个事情。我们给客户会有一个SDK,他用SDK做的话我们就可以在这里面做很多的事情,比如可以对他的节点进行实时监控,他的推流失败次数以及卡顿次数,通过他推流的情况再结合调度,实时调整他的推流网络。

还有一个非常重要的数据就是离线数据。我们光看实时数据只能对当前某个用户的推流做调优,但对于整个网络的呢?因为CDS或者我们的推流实时网络是不断演化的过程,我们需要通过一些汇总的数据来看,看它总体的卡顿次数、卡顿时长、卡顿率以及它平均推流时长,比如说一个主播平均推了多长时间才推出的,还有他整体的可用性。除了QoS模块还有一个报障模块,是说你可以查到你卡顿的原因,从App一直到SDK,因为他的App里面肯定有我们的SDK,再到服务端,再整理出一个分析报告。

到这儿为止这些工作基本上把推流端相关的优化做的差不多了,这里面只是比较宏观的东西,细节还有很多,比如说编码方面就非常多,都是非常专业领域的东西。

我们再看服务端,还是看刚才的网络,先解释一下这个网络是怎么样的。这里面表示一个收流节点可以通过一系列的线路转发到另外一个节点,这里面所有的节点都是对等的。这个图表示一个流,实际上可以从这个节点到这个节点,只不过看哪个节点离用户最近,这跟传统的CDN节点还是不太一样,这个节点可以进行收流、分流、转发,或者我们后面讲到的对流进行处理。先来看一下假设这是个收流节点,这里面的这两个都是用来做优化的,是离用户最近的,这个流过来以后可以通过线路C直接到这里面。这里面是假设这个节点是坏掉的,这条线路就不能到了,它可以直接绕过去,虽然说延时会大一点。第二条线路也是这样的,就是一个网状的结构。这样子就能做到整个网络是去中心化的网络,比如我们现在很多的海外用户,有些做跨境电商购物的,我们要上海外节点就非常方便,他可以直接在日本或者新加坡上一个节点就可以了,可以通过CDN拉流到国内播。

然后是无状态化,这是非常重要的。这里面的节点只负责一些无状态的事情,比如你收流过来之后我对你的流进行分发,如果这个节点坏了,我就再找一条线路,它不需要维持它的状态,之所以不需要是因为实际上它是有一个多活的调度中心做这个事情,比如说它的线路哪条最优,哪个节点坏了可以实时上报到调度中心。

第三点是智能调度,智能传输就是它能够在全局找一个当前最优的路径,比如我们可以做一个5秒一次的探活以及数据的连接性,这里面也有讲到,通过我们自己的监控中心去做节点的探活以及连通性。还有一点非常重要的,就是一路流过来之后,比如说我在第一个节点到下一个节点,每经过一个节点都会统计增率FPS,看看当前的增率不是有下降了,一般码率不会变化太大,但是增率可能会变大。这样子实时的增率对能整个链路的质量进行监控,比如北京连接的客户,说他卡了,我们知道他连的是哪一个边缘节点,能知道这个流是从哪来,就能比较好的快速定位问题。汇总的数据也是这样的,能通过汇总数据看到当前选的点是不是有效,因为在CDN的行业里面选物理节点非常重要,我们可以通过一些异常的数据来尽快调整这些选点。

网络讲完之后,服务端还有一个重要的内容就是传输协议。我们看下目前常用的几个传输协议有RTMP,能控制在1到3秒以内;然后是HLS能控制在10秒,可能会超过10秒,但是我们现在做到的大概是6到7秒以内,HLS是基于HTTP的协议;然后HTTP-FLV也是基于HTTP的协议,能做到基本上1到3秒内。

如果我们要求实时性,一般会选择RTMP或者HTTP-FLV,能满足互动性比较高的场景。但如果做得比较好的话,它们需要有播放性的支持,很难做成通用的,如果要做的话要对播放进行定制。HLS是比较通用的,因为他是基于HTTP协议,数据流的分发都是基于传统的CDN,它是一个文件的切片,切成很小的片,再不断的去更新他所有的文件,这样子就对已有的CDN兼容性非常好,直接可以用已有的CDN的网络,但是它是单向广播的,互动性比较低,延时也相对比较大。

其实除了这些协议之外还可以定制协议,比如我们的RTMP是基于TCP的,可能会带来一定的延迟,比如可以基于UDB来做,我们可以做到非常低的延迟,比如500毫秒。但是为什么我们没有这么做?对于我们云服务提供商来说,我觉得一个是我们自己去定制的话,协议是不够健壮的。TCB或者UDB都是经过几十年的时间经验,我们再去定制,如果万一以后有什么问题我们可能需要不断地填坑。另外,现在所有的无论是我们自己建的节点,或者是用第三方节点做分发都是基于HTTP协议。当你的用户量不大的时候你可以自己定制协议,比如说场景不超过100人的教室直播的话你可以自己定制。但是如果你的用户非常多,我们再去用一个自己定制的协议,这是非常危险的事情。所以这也是为什么Facebook这种公司,他们可能在尝试定制的协议,但是目前他们还是在用RTMB,虽然是很老的协议,但是兼容性非常好。无论是基于定制还是基于P2P做传输,实际上都是可行的,但是我们作为一个要对所有客户负责的公司,可能不太适合现在去做定制。

在服务端还有另外一个重要的环节就是转码,这个图里面每个节点是对等的,你的数据过来之后在这里面分发到下一个节点过程中,每个节点都可以进行转码。这张图中我给了两个转码节点,第一个转码节点是在收流的时候,第二个是在靠近用户端的转码。

为什么存在这两种情况呢?对于RTMP来说,一个RTMP一般来说原始码率不会小于末端码率的,我一般不太可能把一个500K码率的视频转成1M的视频,所以如果是RTMP传输的话我可能只需要在收流节点转好,之后在内部的转发环节就可以降低他的转发带宽。如果是基于HLS播放的就可以在边缘节点里面去做,为什么呢?因为如果是在这里面转好之后,他里面传输的都是基于HTTP来传输效率就降低了,所以我靠近用户端再转就可以了,需要的时候再转,这是我们做的一个优化。

为什么我们能够做到每个节点都可以进行转码呢?我刚才说到它是一个无状态的节点,比如说转码它只是对文件进行处理的过程,不需要自己维持这些状态,转完之后把这个流分发到下一个节点就可以了。实际上现在有一些比较新的技术可以做到这些的,比如说基于Docker容器的虚拟化,我这里面已经存入了转码的程序,你过来我直接在这里面启动就可以,也就是说这个节点里面本身部了一个虚拟化的计算平台,我直接可以秒级启动这个程序,如果这里资源不够我可以把转码程序调度到另外一个节点,调度也是非常方便的。

对于存储来说我们知道一个流需要对它进行存下来,可能会回看。在社交直播当中存下来的很少,但是为了监管需求也有需要保存下来的。但是在某些场景,比如教育直播,可能需要把一些精品讲师的内容存下来回看,那就需要有一个实时转码或者存储的需求,对存储来说我们可以在靠近存储的机房去转,对于其他的我们可以根据需要来转。这里面从网络、转码以及前面介绍的传输协议,基本上覆盖了服务端的一些优化。

最后就是播放端,它是离用户最近的,就是最后一公里。首先就是首开,用户点进去之后能多快给到数据,首开延迟一般都会在服务端做一个缓存,数据到达客户端能直接解码,这个目前做到的是基于Flash的播放器,能做到0.5秒。如果消除累计延迟的话会有一个做播放控制的缓存,这个缓存对于首开延迟来说肯定越小越好,但是因为用户的网络可能不太一定,比如我在这里面有Wi-Fi,出去之后就要用3G或4G了,特别是在网络切换的时候差距比较大,就会有网络抖动,我们为了消除这个网络抖动带来的影响,会在播放端做一些Buffer,这些Buffer会影响他的首开时间,很大的优化就是如何平衡这两个Buffer的大小。还有一个就是丢帧,关键帧肯定不能丢,因为包含了视频的全量信息,B帧是可以丢的,我们的一个优化是尽量在这个过程当中使用B帧,B帧虽然说压缩效率是最高的,但是因为它其实是向后参考的,解码的时候它不仅要参考前面那个帧,并且要参考后面过来的帧,也就是说这个数据过来到能正常播放可能需要等好几帧才能播,所以会带来比较大的延迟,除非是那种网络非常好或者说解码性能非常好的情况下,要不然其实不推荐用,直接可以把B帧去掉。然后另外一个优化就是自适应码率,在自动播放的时候,比如优酷这种网站会自动帮你降码率,可以做到自适应。

重点看一下基于HTTP的测试性码率是怎么做的。首先播放端发一个请求到服务端get一份数据,我们在服务端有两种码率的数据A和B,分别代表它的码率是不一样,我们会先把它切好存在服务端,然后根据你的客户端的网络来取,你要请求什么样的数据,然后再把它分发给你。

我们看一下,首先播放端向服务端发请求,然后服务端会把这个A码率的数据通过HTTP传到客户端。这是一个非常简单的模型,要做到这个样子,其实服务端做的事情比较少,服务端把它切成多个码率的视频文件存下来就可以了。但是,在客户端还需要做很多事情,我们来看一下客户端需要做哪些事情?

首先它有一个带宽预估模块,就是当前用户的带宽多大,他能承受多大码率的视频拉取,然后通过这个预估结果去选择相应的码率,下一个片断的码率是多大,因为他经常能实时的调整当前用户播放的码率。选择码率之后再有下载调度模块做调度,基于这个就能通过HTTP接口去服务端拉数据了,把数据拉给播放端去播放,然后可以根据它当前的播放效果再把数据反馈回去,比如说我拉一个片断,拉过去花多少时间是可以计算的,然后再预估下一次能不能再拉这么大的,或者说能不能拉更大的,这就是播放端自适应的原理,但是这个是基于HTTP的,其实RTMP也是类似的。有三大模块去控制它的片段的拉取,另外一个就是通过实时的反馈去实时调整码率,但前提是你服务端需要有存这么多的数据,怎么做到的?就是我刚才说的实时转码。

在播放端除了播放相关的模块之外,还有跟推流端类似的QoS模块,负责对播放过程中的性能进行监控,当然这个也可以基于第三方做,比如说听云的监控调优和报警。首先看有哪些东西呢?就是首开时间,我们能做到0.5秒,它是一个平均值,有些可能是0.1秒,有些可能超过1秒,这是有可能的。然后我们需要对这个进行筛选,再统计出来。然后播放的失败次数,到底是进行推流失败了导致不能播,还是因为用户本身的网络失败了,用户没网的话这些数据不能上报回来。还有卡顿次数,播放过程中卡了多长时间,卡的次数多少,除了这个实时数据之外还有离线数据,看汇总的报告来综合评估整个推流和播放的次数,其实主要是网络的效果是怎么样的以及我们用户的网络分布大致是怎么样的。

除了QoS模块还有个报送模块,这个是可选的,用户在播报过程,我们可以把数据上报回来进行分析,无论是优化SDK还是网络都是可以的。

举报 0 收藏 0 打赏 0评论 0
 
 
更多>同类资讯
全站最新
热门内容
网站首页  |  关于我们  |  联系方式  |  版权声明  |  RSS订阅  |  开放转载  |  滚动资讯  |  争议稿件处理  |  English Version