协议选择

最初选择HLS,后面切换为RTMP,切换为RTMP主要为了降低延迟,提供更好直播用户体验。

解决并发问题

  • 分发架构
    采用Live stream server, origin server, edge server 三层架构;如下图如示: ![分发架构图](/images/facebook live arch.png)

一句话就是:通过遍布各地的CDN节点(edge server)实现海量用户的播放请求。

  • 请求合并应对高并发 采用的CDN方案,应对一般数量级的播放是没有问题,但是facebook上有很多名人与网红,他们每个人都有几百万个粉丝,这就要求facebook live 直播系统能够处理超过一亿人同时播放的能力。假如一个名人的直播有100万粉丝同时观看,edge server缓存命中率为98%,那么未命中用户为2万,这2万用户回源到origin server甚至回源到Live stream server,服务器压力可想而知,这不是2W个连接而已,而是2W个视频播放,带宽,cpu都是一个很大的考验。用数字说话,以带宽为例; 假设一个HLS切片为3S,高清视频码率为1800K bps,那么一秒带宽需求为:
1
20K /3 *1800K b/s * 1s =  20*600 Mb = 12 Gb

每秒的带宽超过10Gb,服务器网卡高配也才10Gb。

业务驱动方案,其具体解决方案如下: 在edge server 对同一个视频切片的多人cache miss请求进行合并,只发送一个到 origin server,待origin server 返回该视频切片,同时发送给该视频切片的所有请求。这样就可以大量减少回源的请求数量。origin server亦是如此。

想到下面的问题:

最近520,林心如与霍建华在微博宣布恋爱关系,微博是怎么搞定推送信息众粉丝的呢? 一个直播有100W在线观看,如何实现海量消息的转发?

既然想到了,以微博为例写一下自己的方案:

  1. 微博消息是一种pub-sub模型,简单的在问题的场景下林心如这样明星是pub,粉丝是sub,粉丝数量是7000W
  2. 微博发布了,如何发送到7000W粉丝?不可能直接将立即将消息推送到各个粉丝,不可能是一个推模型,瞬间大并发写与大量存储都会有问题,可能是拉模型吗?拉模型好处只写一条微博,新上线的用户会主动拉取订阅(关注)用户的发布的微博;僵尸用户,活不过来用户,睡眠用户是可以忽略的,怎么触发在线用户主动获取关注的人的动态保证消息的实时性呢?
  3. 在用户线用户定时获取更新,例如60秒定时获取订阅用户是否有更新,这是一个很大的开销,假如微博有2000W同时在线,那么一秒有30多W个拉取更新的请求,每个请求都会查询订阅用户的微博,虽然可以承受的,但是代价还是很大的,同时这种定时拉取会消耗用户的流量,长期下来用户是无法忍受的,所以在线用户拉取是不可行的
  4. 对于在线用户采用推消息,7000W粉丝假设有5%用户在线,那在线粉丝为350W,如果在60S内完成,那一秒要完成60W个推送(发送60W个包,更新60W个用户订阅微博信息),如果整个系统只处理这一件事,是可以的,但是微博大V多,假如1分钟有10个类似的情况,同时也还有其他在线千万级用户(数据是乱猜的); 系统容量是有限的,总会出现抗不住的情况的,墨菲定律告诉我们:这种情况总会发生的,只是我们不知道什么时候会发生。
  5. 抗住是目的,这时候需要作好监控,限流,扩容,降级服务保证核心功能
  6. 针对粉丝数量超过1000W以上的大V进行特殊处理

实现RTMP

选择基于nginx rtmp改造,并开发rtmp proxy,采用nginx rtmp有如下好处:

  1. nginx拥有一个良好的技术生态
  2. nginx的多进程模型能够充分分挥多核cpu的能力
  3. nginx rtmp已经有大量的应用,基本功能可靠
  4. nginx rtmp是基于c语言实现,有良好的性能,当有大量的节点部署的情况下,可以省一大批服务器,能够节省一大笔成本

个人水平有限,若有不妥与错误,欢迎指正,谢谢!

参考

  1. Under the hood: Broadcasting live video to millions