深入理解 IM 系统

架构图

整个系统按层画在一张图上,一条消息的路径用编号标出。首页的简版只有四层和四步;这里是工程版,画到每个部件和每一跳。

一条消息怎样穿过系统:先可靠地收下(步骤 1–4),再异步地送到每台设备(5–7);离线的设备回来时自己拉取(8)。

发送方:Ana 的手机周六还去吗?IM SDK:发件箱、本地数据库、同步接收方:Ben同步游标:每台设备一个手机在线网页离线公网:TCP 或 WebSocket,TLSIM 服务端业务层(旁路)被调用,不在路径上账号与鉴权关系与权限黑名单、禁言、审核发送前同步检查群与成员群的成员表开放接口业务消息、回调连接层接入层,持有连接有状态,随在线设备增长接入调度为设备选网关长连接网关每台在线设备一条连接:鉴权、心跳、收发消息层(收)不丢、不重、有序随消息量增长消息服务按会话分片:去重、分配 seq分发层(发)送到每一台设备随 消息 × 接收人 增长接收方单聊、群扩散写扩散 / 读扩散路由查在线路由表在线推送离线推送同步服务存储层消息和状态有状态,随保留期增长消息存储会话时间线已读游标读到哪在线路由表网关登记,路由查询元数据与缓存会话列表、文件信箱每人一条基础设施消息队列服务发现与配置限流与过载保护监控与链路追踪↑ 同步↓ 异步消息日志持久化的队列IM 之外业务系统App 后端、客服、运营IM 之外系统推送APNs、FCM、厂商通道账号、关系、业务消息唤醒后台的手机12345678
  1. 发送:消息从 Ana 的长连接进入网关
  2. 网关看会话 ID,转给负责这个会话的消息服务
  3. 先看消息 ID 最近见没见过(重发就原样回上次的序号和 ACK;更晚的重发由存储里的唯一键挡住),再检查能否发言、分配会话内的序号,写入消息日志(持久化的队列)
  4. 写入成功后,消息服务回 ACK:发送方只等到这一步
  5. 分发层从日志读取,写入消息存储,再去分发(从这里起是异步的)
  6. 确定接收方,扩散(写扩散时写入每人的信箱),查在线路由表
  7. 经 Ben 手机所在的网关推送。没有在线连接的手机改走系统推送,它只是提醒;网页这里不用系统推送,下次打开时补齐
  8. 离线的设备回来后带着同步游标来拉(游标指向它在自己信箱里读到的位置),同步服务从信箱(写扩散)或群的时间线(读扩散)返回缺的消息;在线的设备发现会话序号断档也会去拉,推送和拉取重叠时按序号去重

蓝色实线:消息的路径蓝色虚线:拉取 灰线:调用、写入、通知虚线框:IM 之外点线:同步与异步的分界

业内常说的“接入层、逻辑层、存储层”:连接层就是接入层,消息层和分发层合起来就是逻辑层。消息日志通常用基础设施里的消息队列实现,比如一个按会话分区的主题。

点任意一层或卡片,看它做什么、难在哪、在哪几章深入讲。