B站直播弹幕系统goim实现分析

goim是B站的直播弹幕系统,整个的设计架构比较简洁,纯go实现。IM系统我觉得也是很经典的系统设计问题,无论做什么业务IM系统都必不可少,当然弹幕这种IM系统和传统的IM有一些区别,这篇文章简单的分析一下goim的设计。

需求分析

直播的弹幕系统和普通的IM系统相比最大的区别是只关注实时消息,不需要访问历史消息,这在设计上就简化了很多操作,比如历史消息的同步,消息如何不丢不重,单聊,群聊,pull,push模式的取舍这些都不用考虑。直播弹幕在用户加入直播间时开始接收消息,离开时停止接收,用户发的消息在直播间内广播,有一些礼物消息还需要在所有直播间广播,针对单个用户还会在弹幕中推送一些系统消息。

架构设计

goim

这是官方给出的架构图,可以看到架构比较简单,一共分为3个模块,comet为接入层,维护和客户端的长连接,logic是逻辑层,负责鉴权、存储路由信息、接收消息的推送请求、将消息写入kafka,job负责消费kafka的消息,将消息推送给客户端对应的comet。客户端的路由信息也就是连接的哪台comet在redis中维护,这样三个模块都可以进行水平扩展,客户端推送消息使用HTTP接口,服务器之间采用RPC通信,服务器和客户端使用长连接下发消息。由于中间加了一层kafka而且kafka是pull模式的,我觉得实时性会差一些。

comet

弹幕的消息量比较大,所以采用长连接二进制协议是比较好的选择,comet支持tcp/websocket,如果用websocket就不需要考虑加密了,直接走https,用tcp的话采用一般的方法先走一个握手流程,客户端用公钥加密向服务器发送之后通信用的对称秘钥,随后的消息使用对称秘钥加密。客户端登陆时首先请求logic的weight接口获得当前comet的负载状况,然后选择一个连接,comet使用服务发现组件注册自身信息。

细节上,为了减少锁争用,将连接打散到多个bucket中,各个bucket中维护连接和房间信息。

logic

logic接收消息发送请求,走的是http协议,可以向单个,多个用户,房间内,全服推送。对于单个用户,可以根据key和mid推送。logic提供connect,disconnect,heartbeat,online四个RPC接口供comet调用,connect完成鉴权逻辑,生成key并与用户绑定,在redis中维护key:cometid和mid:keys:cometid的信息,推送消息时将这些信息附加到消息中写入kafka。disconnect用户离开时调用,清除redis中注册的信息。heartbeat心跳消息更新redis中key的超时时间,online用来更新当前comet房间在线人数状态,在redis中维护。

job

job负责消费消息并向comet推送,同样使用服务发现获得comet节点信息,watchcomet节点的变化,比较简单。

总结

goim这种分层,解耦,扩展的设计思路值得借鉴,之后有时间分析一下传统IM的设计。

# IM, goim

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×