本文为冰河《分布式IM系统》的学习笔记,非本人创作
每个需求背后都是一个技术点,有人能告诉你实现这个功能需要用什么技术是一件多么幸福的事情啊
按照以下逻辑展开:
|— 单聊链路
用户请求链路 — 发送消息链路 —-- 群聊链路
用户请求交互链路
用户可以通过一些方式(PC、H5、小程序、APP)去访问我们的服务器,但是访问的肯定是域名而不是 IP 对吧。所以链路第一步:
- DNS(域名解析)
对自己的服务器是不是要负责,你也不希望它挂掉吧,第二步:
- Kong/OpenResty/Nginx(负载均衡与限流)
听说你做的是分布式?不会只有一台机器吧:
- 系统网关(路由、限流、风控)
走了半天了,处理点逻辑吧:
- 后端平台(应用服务,提供 SDK)
- IM 即时通讯服务(提供即时通讯能力)
把数据的问题解决了,就收工吧:
- 基础服务(Redis、MySQL、其他数据服务)
还是上图清晰:
总得来看,用户发起的请求有两类:
- 调用后端平台的接口,执行后端平台的逻辑,如搜索用户、查看好友列表等不涉及通讯的服务
- 向 IM 即时通讯服务发送消息,IM 处理消息逻辑后和客户端建立长链接进行通信
为什么要留一个这样的通讯方式呢?而不是只有连接 IM 即时通讯服务这一种方式?
发送消息交互链路
对不起我又要偷图了
图画到这里这个链路就很明晰了,从 A 有一条消息到 B:
- 消息中带有 B 的 ID 和终端信息
- 根据 ID 后端平台可以将消息缓存起来,并同时入库
- 当后端平台连上了 B 后开始对暗号,诶,ID 一样
- 就根据 ID 向对应 Topic 发送消息
- IM 即时通讯系统从 Topic 拿到消息并推给 B
(有记录、有缓存、有解耦,完美)
但是依然有问题是图画不出的:
-
“用户 A” 多起来了之后,后端平台是否能满足分布式条件横向扩展?
-
“用户 A 的消息” 多起来了之后,IM 即时通讯服务是否能满足分布式条件横向扩展?
-
在消息的流转过程中,如何选择“对的”那个 IM 即时通讯服务?
看看上面写的,对 Redis 作用的理解出错了吧,Redis 缓存的其实是 ID
单聊交互链路
进一步地讨论单聊的情况,用户 B 在线时,A 的消息会直接发送给 B;而 B 不在线时,A 给 B 的消息会被存起来,等 B 上线后再同步给 B。
但这只是基于单聊这个逻辑的讨论,事实上,由于历史消息的存在,无论 B 是否在线,消息都会被缓存
群聊交互链路
那群聊呢,其实也没有什么不同,对于在线的用户,即时推送消息;而对于不在线的用户,则等到上线后再进行历史消息的同步
💡 只有一个问题,这个广播未在线用户的未读消息 ID,作用是什么?