以下内容是从一个运维
的角度看待问题,主要借鉴了某某云和某站的直播架构总结的经验,还加入了一些自己的思考,希望能在CDN这条道路上走得更远。
一个直播业务,大致分为三步:
可以参考云厂商官方文档的介绍。
主播推流时一般会采集多种数据(屏幕、摄像头、可拓展内容),使用OBS
或者其他的推流软件推流到CDN的节点
,当然这里面还有其他的一些功能的实现,比如说美颜
、水印
、滤镜
等等功能都在推流前
已经处理完毕。
从协议上来讲,直播CDN主要的概念有像素格式、传输协议、视频编码协议、视频封装协议,目前主流的是yuv420(像素格式)、aac(音频编码)、H264(视频编码格式)、flv/hls(视频封装协议)、rtmp(视频传输协议)
详细的协议介绍还需要自行谷歌,简单列举一下直播中会常见的协议
主播的推流配置比较简单,可以参考下图。
当你点击开始推流后,客户端就会向服务器端发起RTMP的握手请求,握手成功后开始检查鉴权,当鉴权通过,边缘的服务器会主动向直播中心进行推流,把流推到直播中心,这个长链接会持续到主播推流结束,不可抗拒的风险除外(网络抖动、节点负载异常等)。
拉流是一个被动的过程,往往是用户向边缘节点发出一个播放流的请求,边缘节点会进行查流,看看自己是否存在流,如果没有会递归到直播中心拉流,如果中心流还不存在,则返回404。
流量入口指的是客户端如何请求到你这个节点的。
一般比较成熟的商业CDN厂商,会在每个节点的LVS上挂N组VIP,后面才是real server,每组VIP有不同的作用,比如说用来区分大中小客户、回源专用VIP、是否使用https等等,用户请求某个域名的时候,会解析CNAME,可能会有多层,在加上调度的决策,你的请求最终会解析到某个A记录,这个A记录就是LVS的VIP。
如果只是给自己使用的自建CDN,一种更为简单并且好维护的方式就是直接使用A记录,机房的每个机器都有个域名解析,这个解析只有A记录和AAAA记录,用户请求的时候会请求调度的接口,接口来返回几个URL,其实就是告诉你哪个机器为你提供服务。这种情况对调度和端的依赖度极高,一般只有自建CDN可以这个姿势使用,后面会有详细的调度介绍。
两种入口方式的优缺点:
CDN的请求最后都是会请求到IP:80 、 IP:443、 IP:1935这种业务端口上,一般监听这些端口的都是Nginx或他的二次开发产品上。nginx会对请求做一层转发,将请求转发到nginx-rtmp模块或者SRS应用上。
当然网关肯定不会只是单单的转发功能,像鉴权
、refer黑白名单
等等功能也是这层实现。
SRS是一个简单高效的实时视频服务器,支持RTMP/WebRTC/HLS/HTTP-FLV/SRT。SRS和NGINX-RTMP相比,支持的协议更加丰富,更符合现代的直播场景。
经过二次开发后的SRS,拥有更好的RTMP拉流体验,之前的NGINX经常会有BUG的存在。降低了进程回源,做法是在网关和SRS前面加了一层微服务(kratos),请求会通过网关转发到kratos,kratos负责和srs交互,krotos知道哪个进程有流,去请求到有流的进程。这样大大降低了进程回源。
地址:https://gitee.com/ossrs/srs
随着架构的更替,回源器的使用场景被慢慢淡化,目前只会对一部分特殊协议(HLS7)文件做类似点播一样的的回源请求而已。
直播流相关的架构升级: 网关(nginx-rtmp)->回源器 网关->kratos->SRS
CDN的日志量非常的大,加上直播对磁盘的要求不高,一般是不会专门给直播准备比较大的机械盘,意味着你的日志空间有限,你需要及时将日志进行上报,这些日志将会在卡顿分析、带宽计算等等场景使用。
直播观看的体验有两个方向,一个首帧时间
,一个是你的时间和你观看直播时间的延迟
。下面介绍一下如果通过quic
来实现降低延迟。
QUIC是谷歌开源的一种基于 UDP
四层协议,在低时延和高可靠有这很好的优势。
运维端是支持QUIC的,使用端请求播放流时,client->边缘节点这个链路就会切换成QUIC请求。节点在回源时也是支持QUIC协议的,能够做到使用QUIC进行回源,这样等于下行链路都得到了加速,从而在这方面达到优化。
在使用QUIC时,也会存在一些问题,最明显的就是QUIC对机器资源的使用,需要控制到一个合适的阈值才行,当然还需要研发测得优化,以免影响性能。还有就是你请求的兜底策略,如果你的QUIC应用挂掉后,该如何切换到使用TCP进行拉流。
带宽信息比较重要的是三个地方,第一个是交换机的出口带宽,另一个是服务器的网卡带宽和业务真正跑量的带宽。
交换机带宽的采集:交换机也可以理解成机房的最后一层保护伞,对交换机带宽的采集方式是使用SNMPv3进行采集的,当然是有前提条件的,你的采集设备在交换机的白名单中。SNMPv3的好处是需要使用账号和密码才可以采集,相当于增加了一层保护吧,SNMP协议采集带宽是使用的OID,不能一下子发送很多任务,否则交换机的CPU负载也是扛不住的。
服务器带宽采集:服务器的网卡采集就比交换机要简单很多,方案是有两个,第一个使用SNMP采集,第二个使用promethus进行采集,大家基本都是这个方案来玩的。
业务带宽的采集:一个机房可能不只有一个业务,比如直播、点播、动态加速业务,分别部署在不同的机房,这个时候你只看交换机的带宽是不可行的。可以使用iptables的方法进行采集带宽,具体的细节可以参考这个连接:https://www.cnblogs.com/feng0919/p/15203395.html
这个文档只是介绍了带宽的采集,那如何排查同集群间回源的带宽呢,这时候需要使用ipset命令创建集群,然后在iptables 中使用match-set。
在CDN节点上部署k8s环境收益是比较高的,配合Deamon使用能让你的边缘节点支持容器批量部署,还可以利用机器闲置时间断跑离线业务。
边缘节点的特点之一就是网络环境复杂,你的机器运营商可能是非三大运营商的节点(移动、联通、电信),所以你的k8S集群的网络需要有BGP的出口,集群的应用一般都放到云上。
Node节点只需要部署Docker和Kubelet这两个应用,可以写好一个Ansible直接批量执行。需要注意的是Docker的目录最好使用独立的挂载点,容器和裸机应用互相隔离,不受影响。
由于K8S环境交给专门的容器部门维护集群,运维只负责维护Node节点就好,维护难度大大降低了,只需要注意Docker的环境是否正常,日志的正常轮转即可
在监控采集方面,建议使用promethus,在边缘节点部署好node_exporter即可获取到了大部分的硬件数据,定制化的业务数据,可以使用cron任务定时执行脚本写到指定目录下来实现上传,如果有精力也可是自己编写一个agent,从平台拉取机器要执行的任务,定时执行即可。
作为业务运维,更需要对业务数据进行采集,主要的数据有:
直播业务目前来看,硬件方面的瓶颈主要是CPU
,直播业务对内存和磁盘的使用率要低的多
,优化CPU使用率可以提高整机性能的使用情况,当然这也需要研发支持。
点直播混跑,点播业务的瓶颈主要是IO
、其次是CPU
,如果一台机器服务既支持点播,又支持直播,整体利用率会有所提升。
直播机器套餐的优化,一个强劲的CPU、64/128G内存、2*120G SSD+500G PCIE的磁盘完全适配直播业务本身。
直播机器属于大流量业务,你的内核参数需要也跟着调优,这个调优是一个持续性的工作,边出问题边积累才能完成。
为什么会有集群的概念呢,是因为可能这台机器上没有这个资源,而同机房的另一台机器有资源,这样只需要同集群回源即可,不需要再次回源获取。
同集群有一个重要的概念,就是一致性Hash
,把机器和请求都做一次hash,好处是,如果有一台机器下线后,不会导致Hash混乱。
那如何把同业务的机器加入集群中呢
节点上线意味着流量的接入,如果你的节点存在异常会导致大量请求失败,造成巨大的影响,因此上线前的检查是不需要做的。主要检查的内容如下:
直播源站在之前的架构中是非常重要的部分,所有的流都推到源站,并进行处理。随着去中心化概念的不断推进,加上核心机房高昂的带宽成本,业务也不断迁移到边缘。下面只是介绍一下,源站一般都会实现的功能和大致实现的逻辑。
直播源站的网关,管理rtmp源站前端的LVS VIP,当有播放或推流查询时,进行调度。将rtmp源站机器上报的流信息汇总,如果某台机器心跳断掉,将不再调度给对应机器,会将此机器剔除。
此应用非常重要,需要稳定的运行,硬件方面 GSLB只需要适量硬件性能的POD和 KV数据库即可。
你的L2回源请求GSLB如果失败,也需要指定好对应的降级策略,如写死某个兜底逻辑,访问GSLB失败直接走到某个域名。
负责存储所有线上的流,承担边缘节点的回源请求,以及直播中心其他集群的拉流请求。
rtmp源站集群的机器会周期向GSLB汇报自己的健康状态和当前在线的流信息。
该应用一般需要十台以上的物理机,不存在同时挂掉的风险,机器挂掉,GSLB会直接踢掉的,目前源站使用的还是NGINX-RTMP,计划更换成SRS,但是源站太稳定了,半年可能才发一次版本,替换计划基本GG。
需要注意的是这部分机器是在内网环境,并且有公网的VIP,意味着你的机器网络配置会比较复杂,注意配置好网络。源站每台机器有大概20个IP,网络复杂度拉满,每次机器上下线需要check好久才行。
这个集群的作用就是让你看到的流延迟变大,单纯的靠源站实现这个逻辑会有些复杂,还不容易维护,因此出现了此集群,主要就是为了解决OTT业务的要求(必须延迟45S以上,该业务的规范)。
此集群会主动的从RTMP源站上拉流,然后再本地存一段时间,然后再推到源站去,当然流名会做变更,全程使用RTMP协议。不使用HLS这种天生支持延播协议的原因是部分电视不支持,被迫使用RTMP。
此集群使用的应用也是NGINX-RTMP。
转码集群就会比较重,主要解决的就是主播推流的原画的码率,转换成不同的清晰度,每道流在转码过程中都会消耗非常多的算力,转码集群在源站集群里算是机器最多的存在,转码也分两种,一部分会使用CPU的机器,一部分会使用GPU机器,具体原理就不太清楚了。
一次转码任务的流程大致如下:
转推集群的工作原理和延播类似,只不过需求场景变了,这个是主动推流到某些地方,一般是推向商业CDN、或者其他源站做备份流。
它负责将一路流从源端中转给目标端,每一个任务会创建一个rtmp
或ffmpeg
的进程去做这个任务。
此集群的作用就是把直播录制成一个指定封装格式的视频文件,该集群对CPU的要求也比较高,CPU算力是改集群的瓶颈。集群主要使用的也是NGINX_RTMP模块。
在去中心化的情况下,改集群也被迁移到边缘,上行推流节点也承担了这个任务。
直播源站对外开放的端口不是很多,以我们的业务为例,RTMP源站出口只有3个公网IP。如果你的通过RTMP源站前面的LVS设备回源,那么你机器网卡带宽的一半都是进行同集群回源,这样会造成资源的浪费,因为你机器只能跑一半的业务带宽。
解决方案是,每个机器除1935端口外,额外监听一个端口,每台机器的端口都不一样,这样可以实现通过端口来分辨机器。
当L2有回源请求的时候,查询GSLB时,会告诉你IP:PORT 的地址,通过此方案大量降低了同集群回源的带宽。
拓扑图如下:
源站都是挂在在LVS这种四层负载均衡设备后面的,一般会使用NAT或者DR模式, NAT模式可以直接在负载均衡设备上统计到带宽,但是DR模式只能统计到入带宽,出带宽统计只能在机器上实现。
思路还是使用iptables,你的机器上会挂载VIP,把不同的VIP走到不同的链规则中即可。这样就能看到不同运营商的回源分布。
CDN的调度系统常见的是下面三种,DNS调度、302调度和HTTPDNS调度,不过最后都是会让用户访问到某一个IP上。你的调度库必须有全量的可用IP和这些IP的状态才行,不然你的调度系统会有调度不准确的情况。当然你还需要购买IP地址库才行,不然你无法确认请求过来的IP是来自哪里的。
每台机器有机器的性能阈值,节点带宽因为涉及到计费,也会有机房的阈值,想要做到精准调度,基础数据必不可少。
这边会有统一的采集机器和机房硬件信息的集群,一般采集CPU和网卡的数据,然后上传到调度系统。这份处理好的数据还有每台机器和机房的MaxUse能力,是否可以调度等等一系列信息,然后让调度决策。
作为CDN的支撑平台,肯定要实现诸多的功能来为CDN保驾护航。下面是我认为应有的功能。
成本是每个公司都离不开的话题,怎样在不影响质量的前提下,压缩成本是冲击绩效的一个很好的方法
边缘节点对比核心机房,虽然网络质量可能会差一些,但是价格比核心机房要低很多,可以尝试在这些边缘节点实现源站的一些功能,比如录制截图,能力足够也可以进行转码。
降低云上资源的使用,云上资源的稳定性是非常优秀的,但是机器的成本太高,可以使用边缘的三线机房替代云上的产品。
市面上会有一些云厂商提供一些类似矿机的社会,这类设备无法使用80 443端口,一部分还是汇聚专线的存在,价钱对比IDC有明显优势。使用上推荐业务应用容器化,使用K8S来编排你的机器,由于每台机器都在不同的地方,没有集群这个概念,可能会导致回源量徒增的情况。改善的方法一个是靠调度,让不同的机器拥有不同的流,当然热流是每台机器都会存在的。第二种是创建逻辑集群的概念,让这些机器通过公网来进行回源。