火爆背后的挑战:直播平台的高并发架构设计
对技术人来说,火爆即是高并发的代名词。越是火爆的平台,对架构、负载容量的要求越高。挑战常在,怎么应战?
兴起及现状
日常生活用手机来看视频的次数越来越多,时间越来越长,看的内容也是种类越来越多。包括最近从3月份美国开始火起来之后,国内也在火的移动视频社交类。这个也是我们现在在重点切的一个垂类,这个垂类为什么现在会火?我们总结下来一部分原因是因为它的娱乐性很强,延迟很低,和主播有强互动的可能,所以越来越多的人在关注。国内现在起码有几家已经上线,有几十家正在联系准备上线,其中总归会有几个火起来的。
这就是对我们现在接触到的这些行业做了一些分类,有综合类的,就是用户产生内容,以娱乐为主,不对用户产生的内容做强的划分。会有一些建议,但是不会强制要求。还有一部分行业性比较强的,像财经、体育,教育这些类。
还有就是最广泛的秀场类的,这个盈利模式也是最清晰的,它的量特别大,主播依赖特别强的这种业务。这部分厂商的核心需求很明确,大部分来自于他们的业务需求,他们擅长做的是装机量,保持高日活,保持主播和用户之间的黏性,然后怎么做商业化,商业化已经让很多人头疼了,这些事情够他们忙,而且是他们擅长的。
但是在多媒体的这部分,门槛很高,以前做点播业务,像两年前我在做媒体云的时候,当时都是点播的业务。做到后面,我觉得点播业务其实并不像想象的那么难,你想你有一个稳定的存储,找一家靠谱的CDN,然后找一个大概能用的播放器就做出来了,这有什么难的呢?你可以找云服务公司,也可以找外包,或者你自己招一个人都能做。但是现在发现到了移动,尤其是3月份移动直播火起来之后,这个门槛突然变高了。因为内容产生方变成了移动端,后面我会详细说。
核心需求
先说一下这个核心需求为什么会出现。大家在看移动直播的时候,如果有人关注的话,会发现那些主播经常问的一句话就是“卡不卡,是不是又卡了,我要疯了,又卡住了”。你们看点播的时候,看短视频的时候,不会有人这么问吧?不会说你们看短视频,它又卡了,这种问题是最近才出现的。真正的客户都已经返回这种问题了,说明流媒体的门槛又变高了,所以他们对流媒体的需求是在增长的。那我们就看一下这些需求都有哪些。
1、首先内容产生方就是推流端,现在主流的IOS、安卓,IOS比较简单,就是那个几个机型,基本大家适配都很好。但是安卓的碎片化是非常严重的,大量的精力都需要做对安卓的适配,而且软编耗电量普遍非常高,手机用了一会就会发烫,都担心会不会爆炸。用户体验就是在不同的网络情况下,上传的视频有可能会卡,有可能不连贯,报各种各样的错误,这个是作为一个开发者他自己不可能去适配的。说白了从用户那边提的需求就是推流端不能卡,画质要好,不能太烫,这是我们接触到的客户真正提的问题,是我们从有点偏技术的角度抽取出来的,它背后对应的是哪些事情。
2、然后是分发网络。分发网络其实躲在一个很后面的地方,用户其实看不见的。真正对分发网络提需求用户也提不出来,所以基本这部分需求都会提给播放端,提的需求也是不能卡,不能花屏,首屏一定要快,一点就要看到,还不能把延时弄的太大。其实这些很多都是和源站分发网络有关系的,只是用户看不到这个需求会跟后面的播放器接在一起。
对这个需求我们做一些抽象来说就是用户的可触达性要好,我们的CDN节点要在全区域、全运营商有覆盖,包括教育网。有很多人,像那些小运营商都会忽视教育网,我们也遇到过这样的例子,教育网确实不好接,因为节点不够多,这其实不是什么难点,只是一个坑,注意到了就能做到。低延时的操作大部分来自端的配合,服务端只要是做好缓存,保证这个数据是连贯的。如果要丢数据的话,把关键帧保留好,丢GOP中间那些PB帧,主要是在端上会收到。
首屏时间,就是用户点开就要看,以前那些开源架构就是rtmp server,它是做不到一点开就能看的,现在一些开源的国内资源写得也比较好了,可以看到。我们是自己开发的,所以也花了一些工作,能保存之前的关键帧的信息,用户一点开就能看,这个就是很细节的东西了。如果这个做不好的话,会黑屏、绿屏,或者是半天看不着图像。
3、在播放器这边也是我们在接业务的时候,遇到用户投诉最多的,因为所有的问题都是在观看的时候体现的,所有的雷都得是播放器的同学去扛。这个需求也是不能卡,不能延迟太高。如果延迟高了,要追回来,追的时候声音不能变,最好是追的策略也能自己控制,这是用户真正提出来的需求。
对于我们来说,要满足这些需求,我们需要做好多分辨率的适配,保证好流畅性,保证好我们追赶的策略不会出现任何异常。所以这三个端很多是相互耦合的,像推流和分发在一起,要保障好用户的流畅性和画质,分发和播放器在一起要保证好低延时和播放的流畅。所有的这些需求里共同的一点就是不能卡,后面我们在设计方案的时候,也是重点考虑怎么能做到不卡。
解决方案
这个是我们这边的系统架构图。最下层是依托金山的云服务,因为我们已经有了很好的平台,提供了我们计算资源,提供了存储,提供了很多自建的节点,当然还不够多,我们还是个融合CDN,然后提供了数据分析的能力。我们依托它做了橙色的这一层,就是我们自己的核心,流媒体直播,然后围绕这个核心我们再做的回看点播、在线转码、鉴权、内容审核。
为什么要做回看点播?因为这不是一个短视频录播的项目,而是一个直播,直播就决定它的并发不会很高,内容不会很多,热点比较少。如果你不回看的话,用户很难维持它的日活,很难维护用户黏度,所以用户一定会要求做回看的。
为什么要做在线转码?推流端其实做了很多把更好的画质想尽办法传上来的工作,投了很多人力来做。传上来之后,观看也在移动端,它不一定看得了。如果他看不了怎么办?我们就需要在线转,在线转码其实承担的更多更重要的事情。
鉴权,用户都不想被盗链,尤其是推流的时候,如果我不鉴权,谁都可以来推,推个法lun功怎么办?这是必须要有的。内容审核,现在我们没有办法帮他做到自动审核,技术还不够。现在做到的是截图,按用户指定的时间定期截图,这样的话,用户就可以请一些外包来看是不是有敏感内容,是不是要下线,这个对于现在这种三四秒延迟的直播来说非常重要。你做不到的话,没准政策因素你就做不下去了。
数据分析一部分是依托金山已有的,一部分是我们自己做的,因为我们延迟性,时效性要求更高。客户会经常大半夜突然提出一个主播看起来特别卡,问你为什么,要是像以前那种方式,一个小时生成报表,然后出体验图,告诉他为什么卡了,客户可没有这个耐心。
我们现在基本能做到5秒间隔就出之前的各种问题定位,这个定位包括从源站收集的数据画的曲线。还有从端上,如果端上用户允许的话,推流和拉流端我们都会有上报数据,几个曲线一拟合,我们就知道问题出在哪里。所以现在不止是RD可以来查这个问题,我们很多售前都在承担着帮用户出这个图的工作。
这个是介绍业务具体的流程图,这个流程图并没有什么特别,只是一般的流媒体的数据走向、各种请求。但是其中有一些坑我可以跟大家重点说一下,首先看一下直播发起流程,这肯定是由应用向自己的服务端去请求一个推流地址,这个推流地址他就用来向我们的流媒体服务器推,然后我们给它鉴权。
鉴权之后,它可以在参数里选择是不是要录像。如果需要录像截图,或者需要HS的分发,我们都可以帮他做,做完之后存到我们的存储里,这也是后面会提到的,我们各个业务之间在做隔离、分不同的优先级,这种后端的多媒体的处理尽量都会依赖别的服务,然后就是正常的结束流程。
这个是实际中遇到的一个问题,现在做流媒体,用户推流,他想知道这个流结没结束,一般互联网公司做云服务都怎么做?都是给回调,如果这个推流结束了,我来回调业务方,让业务方知道我结束了,你可以做你的逻辑了。
但实际操作中我们遇到了问题,就是业务方的服务器没那么可靠,我们可能过去时间特别久,有延时,有丢,或者他们的服务稳定性我们也确认不了,这其实就是一个双方的耦合了。而且它的服务器,由于是我们来调,它的鉴权功能没有办法做得很复杂,他自己的服务器也存在安全漏洞。如果有人来攻击他的话,他的整个业务流程的状态全是乱的。
在试了几家客户之后,我们就改成另外一种方式,也是大家普遍都接受的,就是由APP和自己的Server发心跳,如果APP的网络不异常的话,它自己结束它的Server肯定是知道的。如果异常的话心跳断了,他也会判断出是结束了的。而且我们这边源站服务也会保证,你5秒钟没有数据就一定是结束的了,我们会把你的流给踢掉,这样就能达到用户的业务状态也是稳定的,我们的流媒体服务也是稳定的,而且耦合也会比较少。
这是我们实际遇到的一个坑,这个其实不难,只是看现在普遍云服务提供商还都是在用回掉的方式,所以我特别提一下另外还有一种可选的方式,效果更好。
播放的流程,播放器会先向他自己的服务请求播放地址,然后来我们这拉流,可以是鉴权也可以不鉴权,取决于它的业务形态。如果拉流失败,我们有一些定制化的操作,他用RTMP来拉流的话,我们会告诉他具体是什么错,包括鉴权失效,鉴权参数错误,还是这个流有问题,我们都会在状态告诉他的。这是之前用户提到的需求,说是播放需要知道哪里出了问题,所以我们尽量把状态码都特别详细的返回给用户。包括我们原站也有查询接口,如果他需要那种统一查询也可以来查。
1、推流端实现方案
这是推流端的实现,推流端设计的原则总结下来就是自适应,推流谁都可以做,开源的也很多。但是为什么有的做得好,有的做得不好呢?就是看自适应做的好不好。
总结下来有三点自适应,一个是帧率和码率自适应,这是大家都能想到的。我推流,如果网络卡了,我就降点帧率或者降一点码率,把这个事情做好,把流能正常推上去,不要卡顿。也是这张图里画到的,在发送网络的时候,我们做了一个QS模块,我们团队除了做工程化的人之外,还会有四五个博士专门做算法的。
在这里就有一些体现,我们在码率自适应的时候,是直接可以回馈给编码器的,让编码器动态调整自己的码率,尽量保证质量无损,传出来的视频码率下降,视频平滑。帧率的控制就比较简单了,当我们发现网络卡顿了,我们就会反馈给帧率控制模块。
在采集的时候做一些丢弃的操作,目的就是把我们发送的带宽降下来。这个我们是基于TCP做的,肯定没有UDP的效果好,UDP是我们下一步的尝试,现在还没有开始。因为UDP还涉及到源站的一些架构重构,我们还没有来得及做,现在基于TCP的效果其实已经不错了。后面除了这种简单的自适应之外,我们还加了一个算法类的,那个效果就会更明显。
第二种自适应是软硬自适应,这个很好理解,像硬件编码的优点就是手机不烫,缺点一大堆,用MediaRecorder的话,音视频很难同步,用MediaCodec的话,版本兼容有问题,现在还不太好普及。用软编的话码率低,画质好,除了CPU特别烫,别的都是优点。
怎么能把这两个结合起来?我们现在在做的一些策略性的东西,这个就是个体力活,就我们在自己这边来配置黑白名单,有一些Top50到Top100的高端机型我们用人来测,性能没有问题的话,我们就上软编。因为刚才也听到了软编都是优点,除了烫。
热门机型有一些低端的,软编受不了的就改成硬编。因为硬编是体力工作,所以适配的机型肯定是有限的,没有谁敢保证能够全平台、全机型适配硬编,所以下面的一些非热门机型,我们来不及适配就软编。这样做下来的话,基本能达到99%以上的适配率。在一些大用户那边已经验证过了这个数据。
第三个自适应,算法自适应。我们是真正的第一家能够把h.265做成商业化的公司。现在所有的都在提h.265,不知道大家对h.265了不了解,有没有人听说过h.265可以商业化在Web端无插件播放?我们现在做到了在赛扬机器上可以播30FPS的720P视频,在浏览器上不用装任何插件,这是我们持续优化的结果。当然这个不适合移动的场景,是我们在接另外一个场景的时候用到的。
在移动端我们做到了IOS手机720P编码,做到15FPS,然后CPU不会打满,可能是50%到70%之间。之前数据是打满一个核。这是因为我们之前有很多做算法的团队,最开始是做技术授权,后来想在一些产品上落地,移动直播其实是h.265的一个很好的落地的场景,为什么这么说呢?
推流端的任务是把更好的画质推上来,网络有限的情况下,我怎么能推上来更好的画质?h.265相对h.264来说能把带宽省掉30%。30%的概念是在视频点播类的应用里能省点钱,在初创应用来说根本就不在乎,因为主播更贵,谁在乎这样30%的带宽。
但是在移动推流就不一样了,30%是从480P到720P的变化,就是你本来只能推480P上来的画质,经过h.265这种编码之后能推上来720P的,主播的需求就是网络够好,CPU够好,我为什么不推更好的视频上去呢?这就是h.265的一个场景,我用算法的优势,你的机器只要能够让我做到用265来自适应,我就可以推上去更好的画质。
2、分发网络-多集群源站设计
分发网络是躲在很远的一个地方了,我们当时设计的三个原则就是高并发、高可用、系统解耦,前两个很虚了,只要是做系统都会想怎么高并发,怎么高可用,怎么横向扩展最容易。
我们做了一个多源站,相对于很多公司在做单源站的方式,我们就是为了让用户能更好的触达我们的网络。在各个集群、各个城市做了多源站,现在不光是国内有几个点,在香港和美国我们也各做了一个点。这样怎么能做到横向的扩容和数据与业务中心的隔离,是花了一些心思的。这种方案并不是很难,用一些存储做好同步其实也做到了。
高可用,就像DNS这种,保证服务单点的,高可用都能做到。怎么做到系统解耦,因为传统的CDN只是负责流媒体的分发,我们相对于它的优势就是我们除了做流媒体分发以外,还做了很多多媒体的功能,像截图、录像、转码、多分辨率适配这些东西,这些东西是会影响系统稳定性的。怎么能在这里做到真正的解耦,保证系统稳定是下了很多工夫的。
一些开源服务,也做分辨率适配,但是它所有的转码调度都是由它的流媒体服务来调起的。包括转码的生命周期也是流媒体服务来控制的,他们都在同级部署。其实这是有很大问题的,多分辨率适配和原画的推送和分发完全不是一个优先级的服务。做系统定级的时候就应该把它们分离开,应该分离在不同的系统来做。
多集群源站就是刚才说到的,尽量用三线机房,或者BPG机房,然后在各个城市南北都布点,尽量的更近的触达用户,让用户推流更容易。同时我们在每个源站都部署了金山云的存储,KS3。
部存储的目的也是为了能够更好的保证用户截图和录像的文件的可靠性,存下来之后我们就不管了,交给KS3,当然KS3多媒体服务也是我们维护的。做转码截图,或者是转分辨率合并一系列操作,是由另外一套系统来做,我们把这些多媒体的服务和源站的服务做了解耦。
在线转码是一个非常耗CPU的业务。一台现在很高端配置的24核机器,如果我想转一些画质比较好的视频,每个视频转三个分辨率,这样我转八路就把它打满了,这是很耗CPU的。如果我转了没人看,这个CPU就在那耗着,而且这个是不适合和源站混部的一个服务。
转码要和数据离的近,在那个源站集群的同一机房,我们会申请一些转码的资源,然后由核心机房来统一调度。我们把调度和具体的功能分离开,根据你这个流推到哪,我们就就近在哪里转码。转码也加了一些实时转码的策略。
为什么要做在线转码?因为推流端已经是尽最大努力把最好的画质、最高的带宽传上来。但是播放端不一定看得了,这样我们就需要把它转出来,而且h.265虽然好,但是有个最大的问题就是在移动端的浏览器上没有办法播。分享出来的必须是h.264,要不然去微信或者是QQ浏览器,你是看不了的。
就是如果我用了很高深的技术手段,把你的h.265的视频推上来了,画质很好。但不在我们端上就看不了,你要想分享的话,我们可以帮你转出一份h.264的来分享。转码是一个高CPU占用的场景,如果我不对CPU做合理的分配的话,很快我的机器资源就会被打满。
我们做了两种策略,一种是有限的机器合理调度。我们的转码系统是个分布式,流水线式的,类似Storm那种系统,但是我们自己做得更适合转码。任务进来之后,我们第一个流程不是转,而是分析,看看你是要转成什么样,你是什么画质,大概会用什么CPU。
如果你的CPU占用很多,我会认为这是一个很难再次被调度的服务,比如你一下进来一个占四个核的转码服务,后来再来一堆占一个核的,肯定是一个核的比较好调度,这个机器资源紧张了,我可以给你调度另外一台机器,或者另外一台机器本来就有些空余,现在剩三个核,我接不了四个核的,我只能先接一个核的,所以我们会按优先级,优先分配高CPU占用的任务,然后才是低CPU占用的任务,在流式系统里,会在预分析之后把不同的任务扔进不同的优先级队列,这个优先级队列就承担着去转不同分辨率视频的职能。
而且在后头如果需要降级容灾的话,也是靠这个优先级队列来解决的,每个用户会有配额。我刚才说24和准24路,其实对于一个云服务公司来说这个量太小了。像我之前在百度做媒体云的时候,每天转码量是有30万,我觉得一个业务做大了,一天30万的转码量是很正常的。
这是考验并发的一个项目,怎么能做到尽量的把CPU打平,因为波峰波谷很明显。像h.265这个场景,我们是做了一套实时转码,有人分享就立刻给你转,让用户一旦开始分享的时候,能达到秒开的作用。但是你不看的时候,我们会有策略尽快帮你停下来。因为这种分享出去的视频并不是一个高并发的业务,有人看我们才给他转是个比较合理的场景。
对于那些低分辨率的现在也在逐步上灰度,不是说所有的你分发了,你发起了,我都给你转,我们会逐渐判断,有人看我们才转,尽量节省系统资源。后面也会考虑存储资源,因为每个机房都会有存储,存储是完全不用CPU的,它保证的是磁盘和IO,和我们完全是资源不复用的,是可以混部的,后面我们会考虑一步一步的混部。
CDN的分发环节,分发环节其实有很多东西是需要播放来配合的,比如说现在推流为了保证画质好,我会增加B帧,加大GOP,这样编码出来的视频质量会变好,代价就是我增加了GOP,那我的延迟就会大,用户一定是从上一个关键帧开始看,这样他看到的可能就是5秒甚至是10秒之前的视频,这个对社交类的移动直播是不可忍受的。既然有这种需求,源站就需要把之前的都保存好。但是怎么能让延时被消化掉,就要靠播放端。
3、播放器端实现方案
这是播放端的实现框图,中间少画了一个地方。这就是个传统的播放器框图,没有体现出我们的核心的技术点,数据从网络接收进来之后,经过RTMP的Demux之后,我们是有一个模块的,这个模块会去判断当前视频是否需要被丢弃,这个原则也和我们接收缓存有关系,我们缓存配的是两秒,如果超过两秒,或者超过某一个其他的阈值的话,我们会开启丢弃的模式。
这个丢弃有多种策略,有的是直接丢掉帧,有的是快进。如果做过播放器就会知道,传统的视频追赶一般都是在视频解码之后来做追赶。解码就意味着会耗CPU,尤其是现在如果我想播720的视频,光是解码就基本上勉强实时的话,根本就没有什么追赶的余地了。
所以我们在算法上做了一些优化,我们拿到这个视频的时候会先去判断它是不是一个可以丢的,如果它是可以丢的,在解码之前我们就丢,但是这样丢会出问题,因为解码器会内部不连续,一旦解码器内部不连续了,它可能会产生黑屏,所以我们即使要丢,也是在解码器里边做了一些定制化的开发,还是把要丢的视频传进去,让它自己来丢,它不去解,这样就能达到更快速的把这个视频丢掉,赶上现在的实际主播的进度。
这样的话,如果我们网络状况很好,不担心以后抖动的话,我们能做到从推流到观看是2秒的延迟,但是一般我们都控制在4秒,就是为了防止抖动产生。
刚才说的是丢的这种逻辑,如果想快进,类似斗鱼那种,在一点进去之后,开始画面是很快过去的,但是没有音频,我们现在在做有音频的方式,视频在快进,音频也在快进,这样的话声音会变调,因为采样率变了。以前在做端的经验的时候,也做过这种变速不变调的算法,很多开源的,改改其实效果都能不错,这种算法只要做好逆向优化,放进来之后,音频也能保证不变调。
日志收集,可能日志收集不是所有的开发者都愿意接受的,但是有的开发者是逼着我们要我们做,因为他们需要这个数据来定位问题,就像我刚才说的,经常有人会问,是不是又卡了,这个问题被问多了之后,大家都希望知道为什么卡,端上的日志不收集上来是没有办法定位出这个问题的。我们现在有日志收集的策略在用户同意的情况下,会定期可能几百条打成一个ZIP包发上来,这个数据是我们和用户共享的。
播放器其实我们也趟过坑,最开始我们基于VLC做,因为最开始我们做媒体云是做点播的业务,VLC是个挺好的架构,但是用VLC做追赶这个逻辑就能把人坑死,特别难改。因为它里头一层一层耦合的很重,即使到最后改完了,声音也有卡的情况。后来还是用更简单的框架,自己来写上层的所有控制。所以在移动端的直播场景和点播场景还是有很大区别的,这也就是为什么最近突然又出现了很多在视频语音业务上的门槛。
这页我刚才已经陆陆续续都提到了,就是我们如何来定位问题,如何满足播放器的兼容,还有追赶的各种体验,发包的时候,我们会注意APP的大小。因为我们是一个采集和播放都是由我们提供的端到端的方案,有很多库是可以复用的,如果都用我们的话,我们可以把其中一些库做合并,最大程度节省我们提供的压缩包的大小。
用户案例
这个是我们实际接的一些用户的案例,其中有的主推的硬编,有的主推的软编,很多是产品上的一些细节了。我们也在通过这些案例,分析到底哪些产品适合做社交类的直播,已经看到了有一些有用户基础和关注关系的开始有火起来的希望了,而且也是他的需求提的最多,也是最有意愿上h.265的。一旦你有了这种关系,真的过了试水试错这个阶段的话,就会非常关注你产生的内容的画质,由于我们这是端到端的服务,所以非常适合接入这种用户。
这个是我们能提供的东西,包括我们的网络分发的能力,一些带宽的数据。总结下来就是我们提供一套端到端的服务,因为做到了端到端,每个端的细节都已经考虑到了之后,我们可以做很多优化,因为端在我们手里,所以我们能做到更好的三个自适应,有了自适应就能有更好的效果,也是我们的优势。
老司机介绍
, 金山云视频技术总监,前百度媒体云技术负责人,现任金山视频云技术总监。8年多媒体云和端开发经验,负责过移动端开发,服务端实时转码、分布式转码、p2p项目开发,擅长多媒体领域大数据处理。
延展阅读(点击标题):
全球技术领导力峰会(GTLC)是一场面向技术领导者的盛会,以“重新定义技术领导力”为目标,并期待能推动杰出的技术领导者学习和成长。 GTLC为期两天,主要面向CTO、技术VP及有技术背景的CEO等技术领导者,峰会聚焦技术领导力实践与感悟的交流与探讨,旨在汇聚内涵有深度的独家内容、观点鲜明的意见领袖、水平相近的与会者,为参会者打造高质量的社交平台!
戳阅读原文,了解更多惊喜!
本文系InfoQ原创首发,未经授权谢绝转载。