当我们用SRS快速搭建了视频服务,业务也开始上线运行了,很快就会遇到一个问题:如何支持更多的人观看?如何支持更多的人推流?这本质上就是系统的水平扩展能力,SRS当然是支持的,而且有多种扩展的方法,这篇文章就就详细分析各种扩展的方案,以及各种方案的应用场景和优缺点。
从哪里开始
我们看最简单的视频服务,推一个流,只有一个播放器消费流,我们只需要一个SRS Origin源站服务就可以:
listen 1935;max_connections 1000;vhost __defaultVhost__ {}
Remark:SRS启动时默认就是Origin源站模式。
假设我们把SRS源站部署在杭州阿里云的ECS上,主播使用OBS在上海推流,观众在北京观看,如下图所示:
Remark:虽然地域较远,但ECS是BGP带宽,效果其实不错的。 Remark:虽然只有一台服务器,SRS能支持3K个推流流,或者7.5K个播放,详细参考SRS的性能报告。 Note:可能你实测的数据不同,以上数据是在特定环境的结果,包括:流的码率,服务器CPU主频和带宽能力,选择的协议,SRS的版本等差异影响。
如何支持更多的播放
不管是移动端Native播放的RTMP/FLV,还是移动端浏览器播放的HLS,或者WebRTC播放器,所有的视频服务最终是有播放的,在会议中叫订阅或与会者,本质上就是消费视频流。
在直播场景中,一个流会被非常多的播放器消费,比如一个球赛、国庆活动、一个电商大V的直播,直播对于播放的扩展能力是核心诉求,这也是CDN解决的关键问题之一,当然我们使用SRS也可以构建这样的能力,区别在于CDN的带宽成本会更低,而SRS一般部署在BGP云机房,网络稳定性更高但成本更高。
在会议或在线教育中,一个流可能不会被那么多人消费,比如一个100人的会议,可能一个视频流只会被另外99个人消费,如果在MCU模式下这些流会被合并后被其他与会者消费,如果开启语音激励或者用户选择,可能只有说话的人会被其他人消费,本质上和直播的连麦很像,在视频服务中大部分是不对等的情况,推流的少播放的多或者多太多。
在监控或者一对一聊天场景中,一个流会被少量的播放器消费,一对一就是一个播放器消费,监控可能更特殊些可能没有人消费只有在某些时候才会被消费,比如GB28181使用SIP协议,在有播放器消费流时才邀请摄像头把流送上来。
SRS支持Edge边缘服务器,来扩展源站的支持播放的能力。我们将源站部署在阿里云杭州ECS上,主播从上海使用OBS推流,杭州我们需要支持4K播放,北京我们需要支持8K播放,我们就可以在杭州和北京部署SRS边缘服务器,如下图所示:
Remark:播放器如何找到对应的SRS边缘服务器,可以新增一个调度服务器,播放器请求调度服务器的HTTP API,调度返回边缘服务器的IP就可以。 Remark:调度服务也可使用DNS服务,现在云厂商一般也提供DNS服务,可以根据播放所在的区域,解析到对应的IP上。
这个结构是可以水平扩展的,一个SRS源站,最多可以支持7K个边缘节点。如果7K个节点不够,还可以使用多级边缘服务器,完成无数个节点的扩展能力。
SRS如何用多个CPU
SRS使用单进程单线程模型,可以避免线程切换的消耗,也可以避免并发和竞争条件,所以默认情况下SRS只能使用一个CPU,也就是虽然机器有4个CPU最高能跑到400%,但SRS只能用一个CPU最高只能跑100%。
当然这是默认情况,是有解法的:
- 降低机器的CPU个数,比如申请ECS时只申请2个CPU的,这样就不会有多个CPU的烦恼了。
- 使用K8S和Docker虚拟化资源,使用Docker跑SRS,这样每个SRS最多用100%,但可以跑多个Docker。
- 使用SRS的多进程和集群方案,如果确实需要使用多CPU能力,还是会有方案的,下面详细讲这种。
我们先考虑单个源站服务器如何使用多进程,比如4CPU,单个SRS只能支持7K播放,我们可以扩展4倍能力到28K播放。单进程的部署结构如下:
源站的多进程部署结构如下:
Remark:这种部署结构只能扩展源站的播放能力,因为新增的是Edge服务器,流最终还是要回源到Origin服务器。
当然这种结构如果将源站单独部署到一台服务器后,就变成了上一章所讲的结构了,差异在于上一章的每个Edge服务器还是单进程,没有使用Reuse Port扩展多进程能力,这两个结构是可以结合起来用的,如下图所示:
Remark:在这个结构中,每个Edge服务器上也部署了多个SRS Edge进程,这样可以将边缘服务器的多核能力用起来。
到目前为止,我们更多关注的是播放的扩展能力,如何扩展推流能力呢?下面开始讲这个。
如何收更多的流
推流能力,一般也叫收流的能力,因为推流就是指客户端将流推送到SRS,而从SRS角度看就是把客户端的流收了提供服务。
在SRS的角色中,Edge主要解决播放或下行的扩展能力,而Origin则是解决上行或推流的扩展能力。
Origin源站提供了多个方案来实现扩展,按照上面的场景,我们假设杭州有3K的主播,为了业务稳定性我们不能部署一个Origin服务器来支持3K,这会导致CPU跑得比较高,而且一般源站还需要录制或转HLS,需要预留一些CPU出来做其他业务。
SRS支持Vhost,可以将流分成不同的逻辑域,比如3K个流,我们可以分成2个Vhost,这样每个Vhost的流只有1.5K,可以推流到2个源站,如下图所示:
Remark:我们用两个颜色区分了两个Vhost,对于Edge来说不同的Vhost可以回源到不同的Origin,所以可以从同一个Edge播放不同的Vhost的流。 Note:图中播放器连接的是Edge服务器,实际上推流也可以推到边缘的,没有必要必须推源站。 Note:建议客户端连接Edge,而不直接连接Origin,这样可以获得更好的一致性,比如播放时只需要加Query参数指定vhost就可以,而不用关心Origin会根据不同Vhost有不同的地址。 Note:Vhost的优势是完全独立的源站,不会互相干扰,在客户端指定了vhost,相当于在客户端做了负载均衡,系统结构比较简单,劣势是业务是有感知的。
如果业务不按照Vhost区分,或者一个Vhost的流也非常多,那么SRS提供了Origin Cluster源站集群扩展源站,如下图所示:
Remark:两个Origin服务器之间会互相查询流,若Edge请求的流不在本源站上,会将Edge定向到有流的Origin,详细请参考OriginCluster的WIKI说明。 Note:同样的,建议不要直接推流到Origin,而推流到Edge。 Note:源站集群优势是部署时比较简单,不需要根据业务配置Vhost,劣势是源站之间是需要互相访问的。
值得说明的是,由于源站是流的最终所在地,所以他本质上是有状态的,两个源站并不是完全等价的。而边缘可以认为是合并回源的代理,两个Edge是没有差别的,它们并没有存储流的信息,都是通过源站获取流。因此,推流的扩展能力,比播放的扩展能力,对系统的挑战是更大的。
在监控领域,可能有10万或100万摄像头,如果需要把这些摄像头的流全部推送到服务器处理,那这个量级还是非常的大的。一般会在本地处理后,再把流送到服务器,比如图像识别到摄像头有活动,可以把信息送到服务器,需要观看这个流后,再把流送到服务器。
不建议的做法
发现还是会有少对SRS的误用,这里列出来一些不建议的做法:
- 不建议Forward,Forward并不是扩展集群的能力,而是把流复制一份给别的系统,一般在系统迁移,或者需要两个系统有同样的流时,才需要用Forward。
- 不建议在边缘切HLS和DVR,因为边缘没有流,所以无法切片HLS,只能在有播放RTMP或FLV时,才会去把流拉到边缘。所以如果边缘做HLS切片,会发现播放HLS前要播放RTMP,这是很奇怪的做法。
- 不建议把所有业务放一台服务器,比如有些流是指需要出HLS,有些流只需要DVR,有些流只需要FLV,那么这些流就应该分成不同的Vhost,送到不同的源站处理,这样可以避免互相干扰。比如HLS和DVR需要写磁盘,可能会导致IO负载高,可能会影响到FLV流。
- 不建议把业务做到SRS中,比如无人播放时停止推流,那么不应该让SRS断开连接,而应该业务系统观察到无人播放时,通知推流停止推流。这样可以让SRS集中在流媒体处理,而不是因为业务代码Crash。
- 不建议Edge前面挂F5或Proxy,Edge本身就是Proxy,再挂个Proxy意欲何为呢,流量一点都没有节省。有些可能是为了让客户端访问的IP保持一致,那么可以用DNS域名方式,这样客户端看到的都是一个DNS名称,会解析成不同的Edge的IP。
还有些值得特别说明的:
- 以上扩展能力,可以组合使用,比如源站可以是单个SRS,也可以用一个Origin和多个Edge组成小集群源站,再让Edge使用Reuse Port对外就是一个IP和端口。
- Edge拉流可以支持多个协议,对于扩展同样是适用的,比如WebRTC也可以使用Edge扩展播放的能力,同样GB28181推流后播放的协议和源站架构无关。但目前WebRTC推流和源站集群的能力还在开发中。
- 一般来说,Edge就是为了扩展播放的能力,但推流也可以走Edge这是为了让推流的地址更简单,而不用关注Origin的部署结构。一般来说,源站Origin是为了扩展收流的能力,但对于WebRTC这种结构,可能没有固定的Origin和Edge,它可能需要的是一种切换角色的能力。
更多内容,请点阅读原文看Wiki,记得给SRS star哦。