本文来自网心科技首席架构师李浩在LiveVideoStackCon 2017大会上的分享,李浩回顾了从迅雷时代到网心科技,P2P CDN的演进,以及挑战和应对方案。
文 / 李浩
整理 / LiveVideoStack
大家好,我是来自网心科技的李浩,今天和大家分享一种新型CDN架构,汇聚家庭用户的闲置网络和计算资源构建的共享式CDN,整个过程会面临很多的技术挑战,下面会做些分析并介绍下解决思路。
我们的理想
我们希望通过共享的方式来降低企业计算成本,节约社会资源。共享经济的模式这几年发展很快,说实话迅雷当年搭建了一套业界最大的利用共享计算资源来做内容分发的网络,网心继承了迅雷的技术优势,想用一个更标准化的方式对外提供一套高性能和低成本的商用服务。
有调查显示现在生产出来的商品能10倍覆盖我们当前的需求量,包括带宽、存储、计算这些数字化产品和服务。Uber、Airbnb这类产品为什么能火起来,就是因为提供了所有权向使用权高效转移的途径,盘活了巨大的存量资源。我们的目标是盘活家庭用户拥有但很难完全使用的计算、存储和网络资源,使服务节点下沉在用户家中,在网络的最边缘提供实时的服务,第一个切入点就是CDN市场。
现实与挑战
从前两位嘉宾的分享可以看到CDN要做得事情很多,远不止缓存分发一件事情,需要提供一整套的多媒体传输、编解码、截图、存储、运营服务。我们要在该功能集上面把共享资源有效的用起来,更会碰到一些额外的挑战。首先,节点之间的连通性,如何在全球Nat设备分布最多的国家达到一个超高连通率。其次,波动场景的应对能力,质量波动相对来说好解决一点,容量波动是难题,IDC带宽容量是有保障的,但在家庭环境下,有很多应用在同时运行,多个家庭共享有限的小区带宽出口,无法保证稳定的资源容量和全局资源视图。同时,不同协议的传输优先级,多个家庭节点之间网络距离的精确测定,用IP判断无法达到小区级的精度,多端数据共享,提高流量放大比等问题都需要有效解决。
直播架构
以典型的直播场景来展开介绍。主播推流和回源拉流构成数据输入,输入数据以后CDN主要做两件事情,一个就是流数据处理,包括协议转换、转码、截图、转点播等;另一个是中转分发,其中最核心的是组网策略,我们通过玩客云节点做了一次末端流量放大,同样的由于链路增加一跳,组网复杂度指数级增加。为了达到更高的放大比,玩客云节点订阅直播流的一部分信息,SDK需要并行从多个玩客云节点获取编码的切片数据然后还原,封装为标准的http-flv、hls数据流给到客户端。最理想的情况下,对于1Mbps的热流,一个10Mbps上行能力的末端节点,由于数据编码和分片策略的存在,可以达到1000倍以上的放大比,带宽压力完全下移,远优于传统p2p方案。
架构实例
从数据流层面看,数据进入系统后,在IDC节点内部上行转发时会做多份拷贝,避免单链路的问题,因为这里是整条链路最脆弱的一环。下行主要是按需回源,但对热流和冷流做一些区分处理,冷流对CDN的需求是中转加速的需求,好比北京电信的一个主播在直播,全国就覆盖了十个观众,命中率和流量放大等指标基本没有意义,系统核算内部链路成本后不会使用到共享计算节点,最核心的诉求就是缩短中转加速路径。热流需要在内部分发路径上做冗余保障,数据分片配合编码纠错是一个不错的方式,同时尽可能使用共享节点来提高放大比,跳数带来的内部带宽完全可以消化。
内部组网架构
上面列出了我们内部组网的几次演进,最开始是固定的树状结构,根据运营商的拓扑结构,选定两到三个多线路BGP节点做为源,同时根据运营商拓扑结构选出区域中心点,例如华北、华东这些地域,组成一个比较清晰的三层架构。因为结构层级很清晰,路由都是按照预定好的规则去设置,便于研发和运营,一开始起步选这种结构,我觉得是合理的,但是到后面呢,就会发现,它很便于运营,但是它特别依赖于运营,需要运营人员对整体的网络拓扑结构非常了解。举个例子,假设核心源点一个选择了河南,一个选择了广州,那么你可能会出现问题,2015年底的时候,电信的京汉广骨干经常瘫痪,一瘫痪两个点全都不能用,我们需要知道中国的骨干链路是怎么建的,需要能支持这种骨干之间的容灾,是一个依靠人的强运营网络。
第二种方案是很自然演变过来的,把规划好的区域和源节点抽象成节点池,比第一种方案多一套路由系统。不再依赖之前设定的静态路由规则,假设之前设置的华东节点只能走华东和华北区域中心,现在可以通过一些探测算法来动态选择,我们有一些专利算法,例如eqv算法会通过丢包、重传、延时数据来和关键业务指标拟合,通过训练好的拟合参数来为每一条有基础网络数据的链路评分。其次影响路由的还有成本权重,本来回源北京节点是最快的,质量可能是98分,但是从山东走质量是95分,但是山东能直接命中,北京需要回源多一跳成本,那对于能接受95分质量的业务应该优先走山东。有了动态路由系统后,运营工作量大为减少,主要处理一些资源的缩扩、预知的网络割接等事项就行。
对已经在服务的链接根据路由系统指令,要避免乒乓效应带来的额外开销,就是切A切B切A切B这种场景。同时对直播来说很核心一点,要把数据给无缝的拼接起来,因为无法保证两个不同节点拥有同样的时间起点的数据流,在切换过程中如果上一个节点传到某一个编号的P帧,下一个节点就要跟着下一个P帧就往下去传,这里面可以通过特殊标记或者对帧做哈希的方式来拼接,保证路由生效过程中的观看连贯,否则会产生直播重放等问题很影响观看体验。
这个组网方案一开始非常好用,直到UGC直播火起来后逐渐碰到瓶颈。一些客户高峰会有上万路推流并发,在这种情况下,避免不了很多流是长尾流,长尾流在这种固定的网络层级下面确实会有跳数浪费,对只有两个人观看的,或者只有一个人观看的,仍然要走固定跳数。好比主播在山东推流,北京有一个用户观看,源设置在上海,整体路径就是山东到华北区域中心,再到上海,再后到北京,最后到用户,中间浪费的路径比你真正吐出去的这个带宽多好几倍的,而且可能质量还不如北京用户直接访问山东节点。因此这套组网方式在处理冷流上瓶颈是比较大的。
第三种其实是一种网状结构,但是不是无任何规则的网状结构,待会会详细讲一下规则策略,每一个主播都是一个数据源点,这个对冷流多的场景也非常友好,但是要把数据处理系统给独立开来,需要全局可访问的截图、录播、转码系统的支持难度会提升不少。
最后是我们针对热流、重点流的处理思路,内部分发类似SDK的处理方式是一样的,中间会做编码处理,像刚才有个同学去问Akamai是否会做编码处理,Akamai说因为他们的计算开销太大了没有做过多编码处理。看过13年Akamai出的一些论文,传输过程中会做一些简单正交编码配合简单纠错,把一路数据流拆分成三道去往上推。我们也是做编码处理,只不过我们内部编码处理分两种,一种是简单纠错,一种是复杂纠错,以复杂纠错为主。数据推过来以后,重点数据流编码后按照一定冗余度往上去推,一定的程度的丢包是可以克服的,尽量降低双向的数据交互来降低延时。下行通过无率码编码和分发,中间的节点不需要cache所有数据,下行节点通过多个点并行获取一定冗余度的码片并组合。对热流会分发到所有边缘节点的场景,带宽节省也很显著。
对冷流热流的处理
详细说一下冷流处理,我们的处理逻辑就是组建弱网状结构,根据一定的规则和跳数约束来构建的应用级的组播网。核心的路由系统采用etcd存储全量策略,每一个转发节点会有路由代理缓存部分数据并做一些主备线路的质量决策。对冷流逻辑就是降低跳数,减少中间损耗,上行是被动方式,没人观看的情况下数据就不要往上走。下行的主动路由查询,逻辑也是去提高命中率,这个点如果有数据且质量符合的情况下,不应该再去拓展一条新的路径。
根据数据源和观看分布会有几种场景:无人观看、同省同网、同网跨区等,最复杂的是跨网跨区,这种情况也可以在四到五跳到达,和树形结构的一般场景类似,所以真正在线上运营会发现针对UGC的流能节省一半的内部带宽。因为大部分的冷流,尤其是现在的移动直播,App端会用地理位置信息做主播和内容推荐,冷流的主播和观众很大概率在一个区域内。
热流也会依赖路由系统,对热流核心是快速获取到,尽量保证重要节点上已经存在该数据。因此不再做被动上行,会主动分发的,采取一倍以上的链路冗余。会存在冷热转换的过程,因此路由策略要及时刷新,热变冷暂时不考虑。
最后一跳的难点
最后一跳是共享CDN方案的差异化优势点,用SDK的模式把用户资源用起来,做一层毛细节点放大,通过无速率的信道编码来应对波动和实时性要求。传统的P2P方案数据是顺序强相关,主要靠节点间缓存数据的错时实现分享,延时和分享率互相矛盾,同时需要很多的双向交互和补片策略,无法达到很高的放大比。
我们采用运算复杂度较高的喷泉码方案,因为最后一层的共享节点,相对于20Mbps的平均带宽,4核Arm处理器的计算能力是远超的,对比服务器的万兆带宽和32核处理器。因此采用高复杂度前置编码算法非常合理,采用这种方式的数据码片每个都包含原数据的部分特征,像喷泉一样去往外喷,只需要接住一杯原始数据就解出来了。在这种情况下,基本不需要双向交互,采用订阅的模式,告知需要原始数据的比例,上行节点按照比例随机给出码片。
启播过程中通过服务器拿到首帧和音视频描述信息,同时找共享节点订阅,根据fps、cps指标来判断节点吞吐状态,流量逐渐倾斜至共享节点,如果节点资源不足,也可以逐渐倾斜至服务器节点,过程是平滑的没有硬切换。同时每个码片包含原始数据部分特征且不重复,因此从多个节点高并发获取实时数据是可行的,放大比可以很高,对于热流共享节点的1KB码片数据可以分享给上千个客户端。
要达到最高效率,共享节点端要支持全栈协议,同时支持rtmfp、data chanel、自定义,同一份数据可以提供个不同的客户端,C化rtmfp协议难度很高。
内部传输策略与难点解决
效果展示
还有很多策略细节,例如点播业务在播放前放广告,可以采用慢速启播直接走共享节点分发,成本会节省不少。
传输协议以UDP为主,同时保存TCP快速通道,传递音视频描述、控制信令这些关键数据。
波动的应对参考BBR,对链路质量做评估,估算出最佳冗余率,核心目的是避免补数据拉高延时。
编码算法优化,常规喷泉码算法实现是N3复杂度,无法在线上实用,这里权衡了度分布做了很多效率优化。
调度还有一些问题可能要去处理,除了质量和成本的策略,还需要关注容量波动,我们采用双端判定的方式,调度给出优选节点列表,客户端根据调度的节点主动选择,服务节点可以根据自己的负载和cps指标主动断连。节点间的拓扑分布会利用定时的traceroute探测来计算。
上行的第一跳受限的可能是物理通道,我们推出了一款电信、联通、移动的三通道推流器,根据链路质量做负载均衡,数据同样采用喷泉码方式推送,很适合户外高清直播场景。
从目前实际的效果数据中可以看出,在弱网场景下的传输优势还是很显著的。
共享计算展望
CDN是共享计算的第一个切入点,也只是平台上的一个服务插件。我们的希望能通过轻量虚拟化的方式,统一底层的赚钱宝、玩客云资源,对外提供一套标准化的云计算服务,降低分布式存储、AI训练、流量分发等场景的服务成本。
Q/A
Q1:刚才你讲到那个冷流调度的时候提到有些路径的规则会提前下发下去,但是在冷流这种流维度的情况下应该不是用下发规则来实现的?
A:冷流路径是不提前下发的,但是我们会有些规则规约,就是最理想的情况下它是个纯网状结构,无论在哪个运营商,只看延时丢包等网络指标。很有可能直播流推到了北京联通,那么北京电信,或者河北电信的用户访问,直接通过北京联通访问,假设我也能知道这个网络情况OK,这种是最理想的情况。但是这种无预制规则的网状结构,对判断准确度要求很高,而且也会产生很多切换开销,运营难度高。因此我们会定一些规则,就好比,我们还是要坚持同运营商优先,主播是北京联通,那么用户是河北电信,访问路径还是河北电信到中间的一个双线中转点,再到北京联通,在这个过程中我们坚持的是一些预制规则,而设置固定路径,通过这些规则,路由系统动态生成路径。
Q2:那在找冷流的路径这个过程中会有个中心的状态服务存在吗?
A:会有。上面已经介绍,单机上会有一个路由代理,其次有个中心路由服务,中心路由服务用etcd记录全局信息,路由代理会缓存一些路径信息同时有部分主动决策能力。
Q3:一般来说,小运营商和大运营商网间的质量不会太好?这个怎么保证呢?
A:尽量保证网内汇聚,降低出网流量,根据运营商的拓扑结构合理选择网间节点,通过一些汇聚线路来做中转,避免用户直接跨网访问。
Q4:前面有讲到C化,如果C化这部分对用户的设备寿命有什么影响?
A:C话是指共享节点上的服务进程能执行rtmfp协议,可以和flash客户端直接互通,flash会看作一个对等peer,和用户的硬件设备无关。难点是rtmfp非公开,通过字节码逆向分析难度高。
Q5:使用设备上的一些存储空间之类的吗?
A:闲置资源包括带宽、存储、算力,但是对直播这个场景下我们不需要用存储,纯内存的,对点播这种场景需要提前做一些部署的,大家知道迅雷的离线下载,现在接近百分之百全都迁移到了共享计算平台上,迅雷的离线下载服务也相当于我们下面的一个插件。
Q6:问一下,就是我们用户那种节点,它那个如果是宕了,得多长时间能从网络里替掉?
A:刚才说了去做双向选择,用户节点如果宕了,这个控制权应该是SDK层面就立马去把它替掉的,我们不管是宕了,还是网络中断了,就是它没有按照规定的CPS去吐数据,我需要淘汰它了,因为它的长上下线是很频繁的,无法根据完全调度来下发指令决策,调度根据几次心跳十几秒的时间来确认的状态也不实时。调度给到SDK的服务节点数是有接近一倍的富余度的,SDK会自己判定。
Q7:他会有很大量的备份?挂了立马就去连别的?
A:是的。
Q8:我还有个问题,如果是边缘,用户节点这个地方,它一般那个带宽量很有限,我们假设建立了几个连接,我的意思是你怎么限制它那个带宽呢?就是我可能很快就已经把带宽跑爆了?
A:首先对数据进行编码切片,通过几十个共享节点同时提供数据,订阅过程中会指定希望获取该路流多少比例的数据量。同时上面介绍过容量判断策略,后端节点是有剔除链接能力的,如果共享节点监控到cps等服务指标下降,会主动断掉部分链接,避免出现雪崩。