不能再详细了!IM消息系统的设计和实现一文全解
一、名词解释单播:服务器发送消息给单个客户端用户多播:服务器发送消息给多个客户端用户组播/广播:服务器发送消息给一组客户端。有组ID来标识这组用户上行消息:服务器发送消息给一组客户端。有组ID来标识这组用户下行消息:服务器端给客户端发送消息二、系统架构proxy:部署在边缘机房,客户端通过智能dns就近接入logicService:处理认证、心跳、上下线、进出群pushService:单播,广播,
·
一、名词解释
- 单播:服务器发送消息给单个客户端用户
- 多播:服务器发送消息给多个客户端用户
- 组播/广播:服务器发送消息给一组客户端。有组ID来标识这组用户
- 上行消息:服务器发送消息给一组客户端。有组ID来标识这组用户
- 下行消息:服务器端给客户端发送消息
二、系统架构
- proxy:部署在边缘机房,客户端通过智能dns就近接入
- logicService:处理认证、心跳、上下线、进出群
- pushService:单播,广播,接收到消息后转发给comet,之后再由comet把消息发出去
- imService:聊天服务器,处理单聊群聊,离线消息
- cosumerService:对群消息进行异步写扩散
- authService:认证服务
数据结构
cacheService 维护全局在线用户,是一个二级map user_id -> conn_id -> server_id。
- user_id 是业务指定的,唯一标识一个用户
- conn_id 由存储进程分配,唯一标识该用户的一条连接
- server_id 标识这条连接属于哪个接入进程
接入进程proxy维护自己在线用户,user_id+conn_id -> Connection
- Connection 是客户端连接的封装,可以向它推送消息
接入进程proxy维护连接房间信息,room_id -> ConnectionList
三、消息模型
3.1 读扩散模型
- 优点:只写一次,降低了写入次数,特别在群模式下
- 缺点: 同步消息的逻辑会比较复杂,接收端每个会话都要读取一次,放大了读,会产生很多无效请求。
3.2 写扩散模型
- 优点:拉取消息的逻辑简单
- 缺点: 放大了写,单聊要额外写两次,群里要写N次
四、实现方式
4.1 单聊
4.1.1 设计目标
4.1.2 在线消息
4.1.3 离线消息
4.1.4 检测消息丢失
4.2 群聊
4.2.1 设计目标
4.2.2 小群(写扩散)
4.2.3 大群(读扩散)
五、高性能分析
瓶颈 CPU > 带宽 > 内存
5.1 容量规划:(阿里云主机16C32G-2.5GHz,预留50%余量)
- 10,000 conn per proxy
- 100 proxy
- 50 logicService/cacheService/pushService
- or 改进: 10 logicService 5 pushService kafka cluster zookeeper cluster 10 cacheService
5.2内部通信无瓶颈,可水平扩容的路径有:
- 客户端发起的RPC mobile -> proxy -> micro
- 上线/下线/切换房间/心跳 mobile -> proxy -> logicService -> cacheService
- 单播 micro -> logicService (-> cacheService) -> pushService -> proxy -> mobile
- 在线信息查询 按用户查在线查房间 /session
5.3 内部通信,可能有瓶颈的路径:
- 批量单播 micro -> logicService ((N-parallel)-> router) -> pushService -> proxy -> mobile 限制:一批用户总数,不宜过多
- 广播 micro -> logicService -> pushService -> proxy -> mobile 限制:由于pushService定期absorb proxy上的room list, so pushService数量不可过多 改进:logicService和pushService解耦,用kafka连接。由于 pushService 对 CPU 的消耗在 proxy/logicService/cacheService 中最少,只需要非常少的 pushService 实例就行。
- 在线信息查询 查在线总数 /count 由于logicService定期absorb cacheService上的room users,只能是有限的logicService打开counter定时查 按房间查用户 /room 同 /count 遍历 /list 调试用接口,别用于服务
5.4 proxy性能瓶颈
5.5 rpc性能瓶颈
六、高可用分析
为用户提供 7-24 小时无间断服务。迭代式开发,要求内在模块和业务服务的升级、扩容对用户无感知。
- proxy 无状态服务,重启、升级时,客户端检测到连接断开,自动重连到另一个 proxy
- logicService 无状态服务,重启、升级时,proxy 会自动寻找下一个 logic
- pushService 无状态服务,重启、升级时,有其它 pushService对外提供服务
- cacheService 有状态服务,重启、升级时,由备 cacheService 顶上;升级完成,切回主 cacheService
- imService 无状态服务,重启、升级时,有其它 pushService对外提供服务
- mysql:使用mysql master master机制来保证
- redis: 使用哨兵机制来保证可用性
七、异常情况处理
- 如何防止消息丢失(接收端上报已接收的最大消息id,异常服务端重发)
- redis主从切换引起自增id不连续
- 怎么提高proxy广播的性能
- 怎么避免rpc的单条连接成为瓶颈
八、低成本、安全
- 几乎没有外部依赖,极低的运维成本
- 高性能的代码实现,节省服务器成本
- 集成认证鉴权,也支持 HTTPS
(完)
更多推荐
已为社区贡献2条内容
所有评论(0)