上几篇介绍了如何实现一个百万级别的语音聊天室, 本篇将介绍直播平台的设计. 开始分享这个项目其实有点犹豫, 因为我所参与的直播平台跟业界常用的方案不太一样. 但是仔细想想, 架构设计本来就是在各种条件约束下的因地制宜, 没有绝对的正确和错误, 合适才是关键.
我们是国内做直播相对比较早的团队, 也缺乏一些行业通用方案的参考, 因此很多地方是自己通过踩坑摸索出来的. 因为最开始我们产品只支持语音聊天, 后来随着直播业务 (娱乐直播, 游戏直播) 的普及, 才开始支持视频直播, 所以最朴素的想法就是, 直接把语音服务的架构拿过来用.
上篇介绍了语音聊天室的完整架构, 我们的设计就从这里开始. 视频服务可以用这种架构吗? 答案是肯定的. 把上图中的语音数据替换成视频数据就可以了, 唯一的不同是语音聊天室多个用户可以同时说话, 但是直播平台就只能有一个主播.
但是, 随着业务不断增长, 问题开始出现: 一个 SET 内的房间数量到达了瓶颈. 为什么呢? 这要从语音服务器的实现说起.
如图所示, 每个语音服务器为每个房间维护 6 个语音通道(采用循环队列实现), 其中 5 个通道分别缓存 5 个用户的语音数据, 第 6 个是混音通道. 没错, 是 5 个用户, 聊天室的设计就是最多只支持 5 个用户同时说话, 因为同时说话的人再多就会听不清楚. 那其他人想说话怎么办? 一般的做法是聊天室的抢麦或者用户多长时间不说话就自动放弃通道, 或者像 LOL 这种游戏团队设计就只有 5 个人. 混音通道实际上就是把 5 个通道的数据根据时间顺序放到一起(当然还有一些其他处理), 听众收到的是混音通道的数据.
视频服务器因为每个房间只有一个主播, 因此只需要维护一个视频数据通道, 实现上与语音服务器类似. 按理说, 视频服务器应该更简单才对, 但是却有别的问题.
之前说过, 语音服务器是按照 SET 来部署的, 一个 SET 包含多个语音服务器, 房间分布在一个 SET 内的机器上. 因此通常一个房间会分布到多台语音服务器, 这样主要是为了用户的就近接入. 那 SET 内的房间数受什么制约呢?
之前没有介绍的一个细节是, 下图所示, 如果一个房间分布在多台语音服务器, 这些语音服务器上都需要维护这个房间的 6 个语音通道(为什么不是只维护混音通道, 大家自己思考), 因此房间数的制约主要在于单台服务器的内存大小.
因为语音数据是很小的, 一个包大概 300 多字节, 6 个语音通道占用的内存大概几 M, 一台 4G 内存的机器就可以承载上千个房间. 按照之前的计算一个 SET 10 台机器可以承载 20 万的用户, 上千个房间几乎是不可能的, 因此对于语音服务, 内存的瓶颈是不存在的.
但是对于视频服务就不一样了, 视频数据可是很大的, 一帧的数据有时候可以达到几 M, 1 个数据通道都可能占用几十甚至上百 M 的内存. 因此单服务器可承载的房间数可能只有一百个, 也就是说单 SET 的房间数最多只能有一百个, 这里就是瓶颈所在.
大家注意了, 这个瓶颈是无法通过平行扩展增加机器来解决的, 因为每台机器都受到这个限制(当然可以给每台机器加内存来解决, 但是这种做法一方面增加了成本, 另一方面增加了故障的概率). 这是一个系统架构导致的问题, 解决方法可能很多, 例如摒弃分 SET 的架构, 或者把 SET 机器数减少等等. 可以说, 这个问题把我们从最开始闭门造车的野路子拉回了业界的通用标准.
做过直播的同学应该对上面的图都很熟悉, 它是一个典型的直播平台的架构图. 这个图跟我们最开始的架构有一个最本质的区别是, 我们采用了别人的 CDN. 为什么要加 "别人"? 因为我们之前实际上是在尝试做自己的 CDN 来实现数据的分发. 但是这条路走下来是个无底洞, 我们没有别人的资源丰富和专业. 因此, 上面的架构中, 我们只负责生产数据, 我们维护主播上传的视频数据, 并把视频资源信息上报给回源服务器. 用户打开直播时, 先去 CDN 请求数据, 如果 CDN 没有数据, 就会到回源服务器查找资源地址, 并向资源所在的视频服务器请求数据返回用户. 下次用户打开视频的时候, CDN 就直接从自己维护的数据通道中获取视频了.
本篇主要介绍了视频服务架构演进的过程, 描述了从最开始照搬语音服务的架构, 到面临架构瓶颈时, 转而采用目前业界通用的架构的思路历程. 架构设计跟项目所处的时代背景和阶段密切相关, 每个阶段都有其局限性, 不能因为技术发展而完全否定原来的设计思路, 现在所谓的业界标准也是从一次次的踩坑中走出来的.
来源: https://www.cnblogs.com/htkfsy/p/12496714.html