整理 | 西北
2016年10月29日,由又拍云举办的Open Talk No.26在“魔都”上海3W空间成功举办,这次活动紧张约请直播领域开拓一线的技能大神们聊一聊直播平台的架构与优化,看他们化解项目选型、开拓上线、迭代过程、性能优化中碰着的寻衅与履历。
恺英网络程序经理张皓聪在Open Talk No.26上,做了“直播平台IM系统实战”的主题分享,先容了直播平台“IM系统”的搭建过程。

张皓聪:2010年加入恺英网络,先后卖力过多款手游页游项目,对NodeJS和ZeroMQ有深入研究。目前卖力恺英网络“板栗直播”IM系统的干系开拓事情。
△ 恺英网络程序经理 张皓聪
以下是张皓聪的分享全文
本日我要跟大家分享的是现在非常盛行的直播平台里的“IM系统”。“板栗直播”IM系统从立项初期,到发展致今,已经成为一个功能繁芜,拥有一定稳定性的系统。
1.0版本——速率要快
我们做IM系统1.0版本时,有以下几个需求:
一周出Demo
差不多能用
演示的时候不能溘然崩溃
万一崩溃了不能被创造
性能无所谓
总之,要快速做出来
由于只有一周的韶光,初版的架构搭建得非常大略:
做事端由 PHP 和 NodeJS 组成。PHP 卖力用户账户,注册和登录。NodeJS 卖力长连以及进出房间和推送,做成大略的交互。
第一个版本的前端做事器的构造非常大略,功能很少,仅仅卖力联接客户端,卖力所有客户真个联接。为了担保 H5 也可以利用,因此在长连上选择了WebSocket。
△ IM系统1.0版本架构图
为了确保客户端演示的时候,万一崩溃了也不能被察觉,我们利用 pm2 守护了 node进程。同时让客户端同学做了个自动断线重连。
然后登录流程是这样的:先从PHP获取一个token,接着带着这个token和node 建立连接,node 会在内网向php验证 token 是否有效,末了建立连接。
至于广播方面,利用了我称作组的形式进行广播,所有的房间和私信都是通过组的形式进行广播。
首先,用户在房间里发言的时候,实际上是往特定组发送广播。组的名字是用特定字符开头来归类的。
举例来说,须要向10000房间发送谈天信息时,实际上是向 r:10000 这个组发送信息。此时做事端会遍历该组里所有连接,并发送。
当须要进行全服广播的时候,我们利用一个写去世的、分外的 0 号房间,转换成 gid 也便是 r:0 发送。这将遍历所有连接,向他们发送。
接下来是推送私聊,这里我为每个用户都设置了一个私有的 gid,这样发送私信的时候也相称于发送了广播,做事端可以用相同逻辑处理。打个比方向 uid 20000 用户发送私信,相称于向 u:20000 广播。往后扩展成多进程多主机模式时,也不必知道这个用户目前在哪台做事器上,推送私信就会很方便。
在这个设计中,一位用户是许可加入多个组的。就像群聊一样,一开始就利用这样的设计,往后可以很随意马虎的进行扩展。
由于采取了单点连接的形式,并不须要每次进房间都建立新连接,客户端只要首次进行连接,之后发送要求就可以进出房间,也节省了客户真个开拓事情。
2.0版本——更高的可用性
2.0版本需求:
内测版本
支持扩容
更高的可用性
礼物信息比谈天优先级高
特定要发送回执
当1.0版本完成之后,接下来便是要开拓 2.0 版本。
这个版本里增加了一些必要的需求。
首先,这是一个内测版本。在内测版本中会约请用户利用,并进行测试。
期间可能由于用户数增多,也可能由于我们代码本身的缘故原由或是 bug 造成做事器压力增加,此时会有扩容方面的需求。
第二个是要增加广播优先级的功能,这个很大略,礼物肯定是比普通信息优先级更高的。
末了是特定的回执发送,这个我们目前也还没有实现,但是需求一贯是在的。
△ IM系统2.0版本的架构
上图中可以看到模块数增加了,但是总的来说客户端需求并没有变革,基本流程的连接流程仍旧是先问 PHP 要 token,再去连接 WS。由于我们许可把 WS 支配在多个主机上,在这中间增加了一步便是访问 LB 得到 WS 地址。LB 会轮询的奉告客户端本次应利用哪个 WS,并把 IP 返回给客户端。确保所有 WS 的压力是均匀的。
其余还有一处增加的功能是,由于 WS 已经分离到多个进程了,那么须要一个地方可以用来处理广播。这边我们选择了 redis 的进行广播。
同时其余还支配了一台 redis 是专门用来保存在线列表等数据。
△ 带有优先级的推送
上图是一个带有优先级的推送。
大家可把稳到,我们为每个组的gid增加了一个后缀,这个后缀是用来区分优先级的。
比如说用户进入房间 10000,那么我会把他放到 2 个组,分别是 r:10000._ 和 r:10000.n。
同时 node 也会向 redis 订阅两个同名频道,此时做事端就可以从 2 个频道收到推送,分别是 _(普通) 和 n (优先)。
后端会有谈天信息要推送,会根据优先级,是利用普通频道还是优先频道进行广播。
node 这边会开一个主循环,比如设置 12fps ,每一帧会优先转发优先组(频道)中的,然后才是普通,根据当时压力,将会选择抛弃普通。
3.0版本——业务量增大
3.0版本需求:
业务逻辑越来越多,须要拆分
须要支持热更
更好的广播性能
优化与其他做事的通信
日志系统
支配脚本
到了3.0版本时,需求越来越多,须要拆分。
线上有时候会有bug和做活动,会有热更的需求。
redis 广播有可能涌现瓶颈,在这之前须要须要更好的广播性能。
同时还须要优化与其他做事器之间的通信。
末了还须要须要有一个大略的日志搜集器。
△ IM系统3.0版本架构
这是3.0版本的架构。大家可以看到下面有大量的做事了。实在这些做事原来是在WebSocket里面的,现在把它拆身分歧的进程。
客户端连接这块没有变革,客户端仍旧须要问 PHP 要 token,问 LB 要地址,末了再连接。
这个版本的 WS 功能上更加单一,只卖力转发。
在这个版本里,我们做了一套 RPC 框架,用来方便调用内网各做事的接口。
增加了日志搜集器和API的做事。以及IM系统(私聊)。用户之间可以谈天和查看谈天记录等。
总的来说,功能上没有特殊大的变革,尤其是接口方面是向前兼容的。
△ 通过RPC中转的推送
下面我先容一下RPC做事框架。
我们的 RPC 框架是基于 ZeroMQ 的。利用他的里的Dealer和Router 进行的收发。
ZeroMQ 自带自动重连和负载均衡功能,这方面也不用太操心,节省了开拓韶光。
数据交流格式是JSON,明文传输,调试也会很方便。
ZeroMQ 性能
- E5-2630,8G 内存,千兆网卡的测试结果
# local_thr tcp://:5555 100 10000000
message size: 100 [B]
message count: 10000000
mean throughput: 1097051 [msg/s]
mean throughput: 877.641 [Mb/s]
还有便是我们不再利用 redis 做广播,而改用 ZeroMQ 的 pub 和 sub 做广播做事。这样广播性能就有了很大提升。
4.0版本——更高哀求
IM系统4.0版本的需求
广播和业务分离
优化PRC协议
针对个别地区进行网络优化
到了这个阶段,我们碰着了一些个别地区网络较慢的问题。
△ IM系统4.0版本架构图
我们把 WS 和 LB 放到了代理做事器后面。LB 可以根据不同运营商用户,返回代理了的 WS 地址。
△ RPC做事路由
同时还优化了RPC 做事,我们为 RPC 做事增加了路由器,所有的 Worker 都隐蔽在他后面,这样客户端调用的时候并不须要知道详细 Worker 的地址。Worker 的更新重启也不会影响其他客户端。
广播做事也得以和广播分离,同时实现集群化。
△ 广播做事集群架构图