如何设计一个 70w 在线人数的弹幕系统 ?


如何设计一个 70w 在线人数的弹幕系统 ?

文章插图
 
一、背景
为了更好的支持东南亚直播业务 , 产品设计为直播业务增加了弹幕 。第一期弹幕使用腾讯云支持 , 效果并不理想 , 经常出现卡顿、弹幕偏少等问题 。最终促使我们开发自己的弹幕系统 。性能要求是需要支持 , 单房间百万用户同时在线 。
二、问题分析
按照背景来分析 , 系统将主要面临以下问题:
 
  1. 带宽压力假如说每3秒促达用户一次 , 那么每次内容至少需要有15条才能做到视觉无卡顿 。15条弹幕+http包头的大小将超过3k , 那么每秒的数据大小约为8Gbps , 而运维同学通知我们所有服务的可用带宽仅为10Gbps 。
  2. 弱网导致的弹幕卡顿、丢失该问题已在线上环境
  3. 性能与可靠性百万用户同时在线 , 按照上文的推算 , 具体QPS将超过30w QPS 。如何保证在双十一等重要活动中不出问题 , 至关重要 。性能也是另外一个需要着重考虑的点 。
三、带宽优化 
为了降低带宽压力 , 我们主要采用了以下方案:
 
  1. 启用Http压缩通过查阅资料 , http gzip压缩比率可以达到40%以上(gzip比deflate要高出4%~5%) 。
  2. Response结构简化
  3.  
  4. 内容排列顺序优化根据gzip的压缩的压缩原理可以知道 , 重复度越高 , 压缩比越高 , 因此可以将字符串和数字内容放在一起摆放
  5. 频率控制
  • 带宽控制:通过添加请求间隔参数(下次请求时间) , 保证客户端的请求频率服务端可控 。以应对突发的流量增长问题 , 提供有损的服务 。
  • 稀疏控制:在弹幕稀疏和空洞的时间段 , 通过控制下次请求时间 , 避免客户端的无效请求 。
四、弹幕卡顿、丢失分析 
在开发弹幕系统的的时候 , 最常见的问题是该怎么选择促达机制 , 推送 vs 拉取 ?
Long Polling via AJAX
客户端打开一个到服务器端的 AJAX 请求 , 然后等待响应 , 服务器端需要一些特定的功能来允许请求被挂起 , 只要一有事件发生 , 服务器端就会在挂起的请求中送回响应 。如果打开Http的Keepalived开关 , 还可以节约握手的时间 。
如何设计一个 70w 在线人数的弹幕系统 ?

文章插图
 
优点: 减少轮询次数 , 低延迟 , 浏览器兼容性较好 。缺点: 服务器需要保持大量连接 。
WebSockets
长轮询虽然省去了大量无效请求 , 减少了服务器压力和一定的网络带宽的占用 , 但是还是需要保持大量的连接 。那么人们就在考虑了 , 有没有这样一个完美的方案 , 即能双向通信 , 又可以节约请求的 header 网络开销 , 并且有更强的扩展性 , 最好还可以支持二进制帧 , 压缩等特性呢?于是人们就发明了这样一个目前看似“完美”的解决方案 —— WebSocket 。它的最大特点就是 , 服务器可以主动向客户端推送信息 , 客户端也可以主动向服务器发送信息 , 是真正的双向平等对话 。
如何设计一个 70w 在线人数的弹幕系统 ?

文章插图
 
优点:较少的控制开销 , 在连接创建后 , 服务器和客户端之间交换数据时 , 用于协议控制的数据包头部相对较小 。在不包含扩展的情况下 , 对于服务器到客户端的内容 , 此头部大小只有2至10字节(和数据包长度有关);对于客户端到服务器的内容 , 此头部还需要加上额外的4字节的掩码 。相对于 HTTP 请求每次都要携带完整的头部 , 此项开销显著减少了 。更强的实时性 , 由于协议是全双工的 , 所以服务器可以随时主动给客户端下发数据 。相对于HTTP请求需要等待客户端发起请求服务端才能响应 , 延迟明显更少;即使是和Comet等类似的长轮询比较 , 其也能在短时间内更多次地传递数据 。长连接 , 保持连接状态 。
Long Polling vs Websockets


推荐阅读