直播CDN介绍

0.前言

​ 以下内容是从一个运维的角度看待问题,主要借鉴了某某云和某站的直播架构总结的经验,还加入了一些自己的思考,希望能在CDN这条道路上走得更远。

1.直播CDN介绍

一个直播业务,大致分为三步:

  • 主播推流
  • 直播中心接收流
  • 边缘节点为用户提供分发

可以参考云厂商官方文档的介绍。

1.1音视频基础

​ 主播推流时一般会采集多种数据(屏幕、摄像头、可拓展内容),使用OBS或者其他的推流软件推流到CDN的节点,当然这里面还有其他的一些功能的实现,比如说美颜、水印、滤镜等等功能都在推流前已经处理完毕。

​ 从协议上来讲,直播CDN主要的概念有像素格式、传输协议、视频编码协议、视频封装协议,目前主流的是yuv420(像素格式)、aac(音频编码)、H264(视频编码格式)、flv/hls(视频封装协议)、rtmp(视频传输协议)

​ 详细的协议介绍还需要自行谷歌,简单列举一下直播中会常见的协议

  • 视频编码:H264、H265
  • 音频编码:MP3,AAC,HE-AAC
  • 视频封装:MP4,FLV,HLS,DASH
  • 像素格式:YUV、RGB
  • 传输协议:RTMP、RTSP、SRT

1.2推流的过程

​ 主播的推流配置比较简单,可以参考下图。

​ 当你点击开始推流后,客户端就会向服务器端发起RTMP的握手请求,握手成功后开始检查鉴权,当鉴权通过,边缘的服务器会主动向直播中心进行推流,把流推到直播中心,这个长链接会持续到主播推流结束,不可抗拒的风险除外(网络抖动、节点负载异常等)。

1.3拉流的过程

​ 拉流是一个被动的过程,往往是用户向边缘节点发出一个播放流的请求,边缘节点会进行查流,看看自己是否存在流,如果没有会递归到直播中心拉流,如果中心流还不存在,则返回404。

2.CDN节点系统

2.1节点架构

2.2节点的组成部分

2.2.1流量的入口

​ 流量入口指的是客户端如何请求到你这个节点的。

​ 一般比较成熟的商业CDN厂商,会在每个节点的LVS上挂N组VIP,后面才是real server,每组VIP有不同的作用,比如说用来区分大中小客户、回源专用VIP、是否使用https等等,用户请求某个域名的时候,会解析CNAME,可能会有多层,在加上调度的决策,你的请求最终会解析到某个A记录,这个A记录就是LVS的VIP。

​ 如果只是给自己使用的自建CDN,一种更为简单并且好维护的方式就是直接使用A记录,机房的每个机器都有个域名解析,这个解析只有A记录和AAAA记录,用户请求的时候会请求调度的接口,接口来返回几个URL,其实就是告诉你哪个机器为你提供服务。这种情况对调度和端的依赖度极高,一般只有自建CDN可以这个姿势使用,后面会有详细的调度介绍。

​ 两种入口方式的优缺点:

  • LVS的优点:使用LVS 绑定VIP更适合多组VIP提供服务的场景,可以很好的完成复杂功能的调度
  • LVS的缺点:不管是使用NAT还是DR,都需要维护LVS集群,需要关注LVS的负载和健康状态,如果你的LVS集群挂点,整个节点都会崩溃。配置变更复杂,想要实现方便管理还需要实现LVS的动态读取配置文件
  • DNS的优点: 配置简单,只需要录入一条A记录和AAAA记录就好。
  • DNS的缺点:严重依赖前方的调度系统,相对LVS,机器下线的时间有所延长,LVS会主动把机器踢掉,DNS只能等流量慢慢掉下来

2.2.2 网关

​ CDN的请求最后都是会请求到IP:80 、 IP:443、 IP:1935这种业务端口上,一般监听这些端口的都是Nginx或他的二次开发产品上。nginx会对请求做一层转发,将请求转发到nginx-rtmp模块或者SRS应用上。

​ 当然网关肯定不会只是单单的转发功能,像鉴权、refer、黑白名单等等功能也是这层实现

2.2.3 SRS

​ SRS是一个简单高效的实时视频服务器,支持RTMP/WebRTC/HLS/HTTP-FLV/SRT。SRS和NGINX-RTMP相比,支持的协议更加丰富,更符合现代的直播场景。

​ 经过二次开发后的SRS,拥有更好的RTMP拉流体验,之前我们的NGINX经常会有BUG的存在。降低了进程回源,我们的做法是在网关和SRS前面加了一层微服务(kratos),请求会通过网关转发到kratos,kratos负责和srs交互,krotos知道哪个进程有流,去请求到有流的进程。这样大大降低了进程回源。

SRS的gitee链接如下,国人开源的服务,Wiki非常友善,值得阅读。

https://gitee.com/ossrs/srs

2.2.3.1关于SRS的部署:

​ 我们是通过k8S的Daemon模式起的容器应用,根据CPU的核数,起对应数量的进程。但是在这其中踩了好多坑,下面分享一下曾经踩坑的经历:

  • 容器的日志上报完成后要及时删除,不然你的容器会占用很大的磁盘,这部分日志在你进入容器后才能发现,不易发现,并且可能会写满你的devicemapper
  • docker的目录最好挂在在一个独立的挂载点上,不然当这个挂载点满的时候会触发Pod驱逐,机器服务一下不可用,直接GG
  • 一定要保证本集群内部的端口可用性,因为有很多请求是其他的机器请求过来的,如果同集群网络有限制,则无法正常使用,虽然会有兜底逻辑在,但是会造成回源浪费。

2.2.3.2我们使用了SRS的哪些特性

  • 切片功能,在去中心化的今天,我们放弃了中心的切片集群,使用边缘来进行切片,降低了中心的带宽成本。
  • 视频服务器的存流、回源拉流的基本功能
  • 回调功能

2.2.4 回源器

​ 随着架构的更替,回源器的使用场景被慢慢淡化,目前只会对一部分特殊协议(HLS7)文件做类似点播一样的的回源请求而已

直播流相关的架构升级:
网关(nginx-rtmp)->回源器
网关->kratos->SRS

2.2.5 日志上报应用

​ CDN的日志量非常的大,加上直播对磁盘的要求不高,一般是不会专门给直播准备比较大的机械盘,意味着你的日志空间有限,你需要及时将日志进行上报,这些日志将会在卡顿分析、带宽计算等等场景使用。

​ 老的方案我们使用的是一个应用专门负责日志的上报,将nginx的日志定时移动到工作目录,然后逐行读取和上报,上报完成后,删除这条日志。这样在正常使用时没有问题,但是当一些特殊情况下会出现比较多的异常。当把日志拷贝到工作目录时,有概率导致工作目录的挂载点写满,程序在磁盘写满的情况下无法正常工作。我们的程序本身是用supervisor进行管理,但是磁盘满的话,程序无法正常运行,可能会影响其他的程序使用。其次本身维护一个应用的正常使用也是有成本在里面。

​ 新的方案我们使用的是rsyslog上报,nginx生成日志直接上报,减少一个程序的维护。

2.2.6 低延迟/首帧优化方案(quic)

​ 直播观看的体验有两个方向,一个首帧时间,一个是你的时间和你观看直播时间的延迟。下面介绍一下如果通过quic来实现降低延迟。

​ QUIC是谷歌开源的一种基于UDP 四层协议,在低时延和高可靠有这很好的优势。

​ 我们端是支持QUIC的,使用端请求播放流时,client->边缘节点这个链路就会切换成QUIC请求。我们的节点在回源时也是支持QUIC协议的,能够做到使用QUIC进行回源,这样等于下行链路都得到了加速,从而在这方面达到优化。

​ 在使用QUIC时,也会存在一些问题,最明显的就是QUIC对机器资源的使用,需要控制到一个合适的阈值才行,当然还需要研发测得优化,以免影响性能。 还有就是你请求的兜底策略,如果你的QUIC应用挂掉后,该如何切换到使用TCP进行拉流。

2.2.7 机房/机器带宽的采集

​ 带宽信息比较重要的是三个地方,第一个是交换机的出口带宽,另一个是服务器的网卡带宽和业务真正跑量的带宽。

​ 交换机带宽的采集:交换机也可以理解成机房的最后一层保护伞,我们对交换机带宽的采集方式是使用SNMPv3进行采集的,当然是有前提条件的,你的采集设备在交换机的白名单中。SNMPv3的好处是需要使用账号和密码才可以采集,相当于增加了一层保护吧,SNMP协议采集带宽是使用的OID,不能一下子发送很多任务,否则交换机的CPU负载也是扛不住的。

​ 服务器带宽采集: 服务器的网卡采集就比交换机要简单很多,我们的方案是有两个,第一个使用SNMP采集,第二个使用promethus进行采集,大家基本都是这个方案来玩的。

​ 业务带宽的采集: 一个机房可能不只有一个业务,比如直播、点播、动态加速业务,分别部署在不同的机房,这个时候你只看交换机的带宽是不可行的。我们可以使用iptables的方法进行采集带宽,具体的细节可以参考这个连接:https://www.cnblogs.com/feng0919/p/15203395.html

​ 这个文档只是介绍了带宽的采集,那我们如何排查同集群间回源的带宽呢,这时候需要使用ipset命令创建集群,然后在iptables 中使用match-set。下面为生产环境采集带宽的其中一条规则

2.2.8 容器环境的搭建/部署/维护

​ 在CDN节点上部署k8s环境收益是比较高的,配合Deamon使用能让你的边缘节点支持容器批量部署,还可以利用机器闲置时间断跑离线业务。

2.2.8.1边缘节点K8S的搭建

​ 边缘节点的特点之一就是网络环境复杂,你的机器运营商可能是非三大运营商的节点(移动、联通、电信),所以你的k8S集群的网络需要有BGP的出口,集群的应用一般都放到云上。

2.2.8.2 Node的节点部署

​ Node节点只需要部署Docker和Kubelet这两个应用,可以写好一个Ansible直接批量执行。

​ 需要注意的是Docker的目录最好使用独立的挂载点,容器和裸机应用互相隔离,不受影响。

2.2.8.3 容器换机的维护

​ 由于K8S环境交给专门的容器部门维护集群,我们只负责维护Node节点就好,维护难度大大降低了,只需要注意Docker的环境是否正常,日志的正常轮转即可。

2.2.9监控数据的采集

​ 在监控采集方面,建议使用promethus,在边缘节点部署好node_exporter即可获取到了大部分的硬件数据,定制化的业务数据,可以使用cron任务定时执行脚本写到指定目录下来实现上传,如果有精力也可是自己编写一个agent,从平台拉取机器要执行的任务,定时执行即可。

​ 作为业务运维,我们更需要对业务数据进行采集,主要的数据有:

  • 主要应用的版本信息(可制作版本监控,方便发版)
  • 业务流量监控(方便带宽计算)
  • 流数据(需要你的直播服务器开放接口采集)
  • 网络探测数据(用来判断网络质量)
  • 服务状态监听
  • 各应用机器对硬件的使用(top -b 统计,用来分析性能瓶颈)

2.2.10直播机器的优化方案

​ 直播业务目前来看,硬件方面的瓶颈主要是CPU,直播业务对内存和磁盘的使用率要低的多,优化CPU使用率可以提高整机性能的使用情况,当然这也需要研发支持。

​ 点直播混跑,点播业务的瓶颈主要是IO、其次是CPU,如果一台机器服务既支持点播,又支持直播,整体利用率会有所提升。

​ 直播机器套餐的优化,一个强劲的CPU、64/128G内存、2*120G SSD+500G PCIE的磁盘完全适配直播业务本身。

​ 直播机器属于大流量业务,你的内核参数需要也跟着调优,这个调优是一个持续性的工作,边出问题边积累才能完成。

2.3集群的概念和实现

​ 为什么会有集群的概念呢,是因为可能这台机器上没有这个资源,而同机房的另一台机器有资源,这样只需要同集群回源即可,不需要再次回源获取。

​ 同集群有一个重要的概念,就是一致性Hash,把机器和请求都做一次hash,好处是,如果有一台机器下线后,不会导致Hash混乱

那如何把同业务的机器加入集群中呢

  1. 在平台录入对应信息后,使用调用接口查询,接口会返回同集群且在线机器的IP。
  2. ipset命令把机器到一个cluster中,加入的目的也是为了统计业务带宽使用

2.4节点上线前的检查部分

​ 节点上线意味着流量的接入,如果你的节点存在异常会导致大量请求失败,造成巨大的影响,因此上线前的检查是不需要做的。主要检查的内容如下:

  • 重要服务的进程(Nginx、SRS)是否在线
  • 容器环境是否正常,能否正常拉取镜像
  • 条件允许的话,可以提前拉流测试下是否正常
  • 网络、DNS服务是否正常
  • /dev/shm 内存磁盘大小是否正常
  • 流量接入层是否正常(LVS的VIP是否都挂载好了)

3.直播源站

3.1源站架构

3.2源站的组成部分

​ 直播源站在之前的架构中是非常重要的部分,所有的流都推到源站,并进行处理。随着去中心化概念的不断推进,加上核心机房高昂的带宽成本,我们的业务也不断迁移到边缘。下面只是介绍一下,源站一般都会实现的功能和大致实现的逻辑。

3.2.1 GSLB

​ 直播源站的网关,管理rtmp源站前端的LVS VIP,当有播放或推流查询时,进行调度。
​ 将rtmp源站机器上报的流信息汇总,如果某台机器心跳断掉,将不再调度给对应机器,会将此机器剔除。

​ 此应用非常重要,需要稳定的运行,硬件方面 GSLB只需要适量硬件性能的POD和 KV数据库即可。

​ 你的L2回源请求GSLB如果失败,也需要指定好对应的降级策略,如写死某个兜底逻辑,访问GSLB失败直接走到某个域名。

3.2.2 rtmp源站

负责存储所有线上的流,承担边缘节点的回源请求,以及直播中心其他集群的拉流请求。

rtmp源站集群的机器会周期向GSLB汇报自己的健康状态和当前在线的流信息。

该应用一般需要十台以上的物理机,不存在同时挂掉的风险,机器挂掉,GSLB会直接踢掉的,目前我们的源站使用的还是NGINX-RTMP,计划更换成SRS,但是源站太稳定了,半年可能才发一次版本,替换计划基本GG。

需要注意的是这部分机器是在内网环境,并且有公网的VIP,意味着你的机器网络配置会比较复杂,注意配置好网络。我们源站每台机器有大概20个IP,网络复杂度拉满,每次机器上下线需要check好久才行。

3.2.3 延播集群

​ 这个集群的作用就是让你看到的流延迟变大,单纯的靠源站实现这个逻辑会有些复杂,还不容易维护,因此出现了此集群,主要就是为了解决OTT业务的要求(必须延迟45S以上,该业务的规范)。

​ 此集群会主动的从RTMP源站上拉流,然后再本地存一段时间,然后再推到源站去,当然流名会做变更,全程使用RTMP协议。不使用HLS这种天生支持延播协议的原因是部分电视不支持,被迫使用RTMP。

​ 此集群使用的应用也是NGINX-RTMP。

3.2.4 转码集群

​ 转码集群就会比较重,主要解决的就是主播推流的原画的码率,转换成不同的清晰度,每道流在转码过程中都会消耗非常多的算力,转码集群在源站集群里算是机器最多的存在,转码也分两种,一部分会使用CPU的机器,一部分会使用GPU机器,具体原理就不太清楚了。

​ 一次转码任务的流程大致如下:

  • 业务测触发了某个阈值,下发任务到转码接口
  • 转码集群分配任务到某台机器,该机器会从RTMP源站主动拉流(前提是查询了GLSB知道了流的地址),并在本机进行转码。
  • 转码后会在查询一次GSLB推流到哪台机器上,然后持续的像RTMP源站推转码流。RTMP源站收到后,会同步状态到GSLB。

3.2.5 推流集群

​ 转推集群的工作原理和延播类似,只不过需求场景变了,这个是我们主动推流到某些地方,一般是推向商业CDN、或者其他源站做备份流。

​ 它负责将一路流从源端中转给目标端,每一个任务会创建一个rtmp或ffmpeg的进程去做这个任务。

3.2.6录制/截图集群

​ 此集群的作用就是把直播录制成一个指定封装格式的视频文件,该集群对CPU的要求也比较高,CPU算力是改集群的瓶颈。集群主要使用的也是NGINX_RTMP模块。

​ 在去中心化的情况下,改集群也被迁移到边缘,上行推流节点也承担了这个任务。

3.3源站的高级用法

3.3.1 如果降低同集群回源

​ 直播源站对外开放的端口不是很多,已我们的业务为例,RTMP源站出口只有3个公网IP。如果你的通过RTMP源站前面的LVS设备回源,那么你机器网卡带宽的一半都是进行同集群回源,这样会造成资源的浪费,因为你机器只能跑一半的业务带宽。

​ 我们的解决方案是,每个机器除1935端口外,额外监听一个端口,每台机器的端口都不一样,这样可以实现通过端口来分辨机器。

​ 当L2有回源请求的时候,查询GSLB时,会告诉你IP:PORT 的地址,通过此方案大量降低了同集群回源的带宽。

​ 拓扑图如下:

3.3.2 如何实现带宽的统计

​ 源站都是挂在在LVS这种四层负载均衡设备后面的,一般会使用NAT或者DR模式, NAT模式可以直接在负载均衡设备上统计到带宽,但是DR模式只能统计到入带宽,出带宽统计只能在机器上实现。

​ 思路还是使用iptables,你的机器上会挂载VIP,把不同的VIP走到不同的链规则中即可。这样我们就能看到不同运营商的回源分布。

4.调度系统

4.1调度的实现

​ CDN的调度系统常见的是下面三种,DNS调度、302调度和HTTPDNS调度,不过最后都是会让用户访问到某一个IP上。你的调度库必须有全量的可用IP和这些IP的状态才行,不然你的调度系统会有调度不准确的情况。当然你还需要购买IP地址库才行,不然你无法确认请求过来的IP是来自哪里的。

4.2 调度和节点的配合

​ 每台机器有机器的性能阈值,节点带宽因为涉及到计费,也会有机房的阈值,想要做到精准调度,基础数据必不可少。

​ 这边会有统一的采集机器和机房硬件信息的集群,一般采集CPU和网卡的数据,然后上传到调度系统。这份处理好的数据还有每台机器和机房的MaxUse能力,是否可以调度等等一系列信息,然后让调度决策。

5.平台支撑

​ 作为CDN的支撑平台,肯定要实现诸多的功能来为CDN保驾护航。下面是我认为应有的功能。

  • 机器/机房信息的录入,包括设备的能力和阈值,机器的属性等

  • 上下线操作,在一个地方操作,即可让调度停止此机器/机房的调度

  • 探测能力,探测机器的ICMP、SNMP、TCP(80 443 1935)这些端口的状态,如果异常,自动执行上面的操作。恢复后也能自动上线。

  • IP库的编辑和查询,小运营商经常会租用一部分三大运营商的IP,肯定需要对这部分IP做特殊处理才可以实现调度正常。

  • 上线前的检查部分,检测正常上线,异常时提示错误的地方,并能够强制上线。

  • 回源的配置,直播边缘节点回源到哪个二级节点,二级节点回哪个机房都需要有一个地方进行配置才行

6.如何节约成本

​ 成本是每个公司都离不开的话题,怎样在不影响质量的前提下,压缩成本是冲击绩效的一个很好的方法

6.1更先进的协议

  • 目前主流使用的是H264的视频编码,可以使用H265来降低带宽,H265的压缩率相比前者有不少的提升。H264可以低于1Mbps的速度实现标清数字图像传送;H265则可以实现利用1~2Mbps的传输速度传送720P(分辨率1280*720)普通高清音视频传送。

  • 基于端共享的协议HLS7,升级传统的HLS分片,使使用P2P分享的方式解决带宽。详细介绍可以看(https://blog.csdn.net/vn9PLgZvnPs1522s82g/article/details/118533090)

6.2去中心化

​ 边缘节点对比核心机房,虽然网络质量可能会差一些,但是价格比核心机房要低很多,可以尝试在这些边缘节点实现源站的一些功能,比如录制截图,能力足够也可以进行转码。

​ 降低云上资源的使用,云上资源的稳定性是非常优秀的,但是机器的成本太高,可以使用边缘的三线机房替代云上的产品。

6.3使用更廉价的资源

​ 市面上会有一些云厂商提供一些类似矿机的社会,这类设备无法使用80 443端口,一部分还是汇聚专线的存在,价钱对比IDC有明显优势。使用上推荐业务应用容器化,使用K8S来编排你的机器,由于每台机器都在不同的地方,没有集群这个概念,可能会导致回源量徒增的情况。改善的方法一个是靠调度,让不同的机器拥有不同的流,当然热流是每台机器都会存在的。第二种是创建逻辑集群的概念,让这些机器通过公网来进行回源。

posted @ 2022-04-23 19:55  better_feng  阅读(2659)  评论(0编辑  收藏  举报