深入理解 IM 系统

一条消息从 Ana 的手机到 Ben 的手机,中间要经过什么?

一步步设计一个 IM 系统:从一台服务器到百万人同时在线,每一章只做一个设计决策。服务端和客户端都讲,中文和英文都有。

从全景开始

IM 只做两件事:可靠地收下每一条消息,再把它送到每一台设备,包括离线后回来的那台。

图中没画:音视频通话、端到端加密、多机房容灾、合规留存、搜索。

业务系统你的 App 后端系统推送苹果、谷歌、厂商第三方,尽力而为Ana周六还去吗?App 里的 SDK:发件箱、本地库、重发Ben周六还去吗?✓手机和电脑上的网页版,各自同步公网IM 服务端业务层(旁路)被调用,消息不流经它账号与鉴权好友、拉黑、审核发送前检查群与成员开放接口业务消息、回调连接层和每台在线设备保持一条长连接,能主动推送成本:在线设备数;有状态,重启会让设备集体重连消息层(收)收下消息:不丢、不重、有序;存好就回复“已发送”成本:消息量分发层(发)送到每一台设备:在线就推送,离线就发系统通知成本:消息数 × 接收人数(500 人的群:写 500 份信箱,推约 750 台设备)存储层保存消息、信箱和每台设备同步到哪里,回来都能补齐成本:消息量 × 保留时间(写扩散时还要 × 接收人数)↑ 收下:存好就回复“已发送”,Ana 不再等↓ 送达:推到每一台设备账号、关系离线时唤醒消息日志1234
  1. 发送:Ana 的消息经长连接进入 IM
  2. 存好就回复“已发送”(不是“已送达”),Ana 不再等后面的事
  3. 推送到 Ben 在线的设备;离线时发系统通知,只是提醒
  4. 任何错过消息的设备,回来后自己拉取补齐

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

目前写到:开篇(第 0 章)初稿。

每一章都按这个顺序走

  1. 问题一个具体场景,比如“同一条消息出现了两次”。
  2. 看它坏掉在页面里的模拟器上跑简单方案。
  3. 估算一个纸笔就能核对的数字,说明为什么会坏。
  4. 修好它在同一个模拟器里打开修复,对比前后。
  5. 代价修复要付出什么,别的产品会怎么选。

为什么写这个

讲 IM 架构的文章很多,但大多只给一张最终的架构图,或者讲某一家公司的历史。很少有人一步步讲清楚:一个系统为什么会长成这样。

这里跟着一个聊天 App 从 1,000 个用户长到 100 万人同时在线。系统的四层和旁路的业务层一开始挤在一个程序里,每一次增长都逼着其中一部分被拆出来、做深。

最后几章换成 toB 办公、社区、直播、隐私通讯、客服,以及给别的业务用的 IM 平台,看同样的决策怎样反过来。架构没有唯一正确的答案,产品决定答案。

章节地图

主干跟着一个 App 从 v0 长到 v3,每一站写着它的规模和为什么要长大;然后是稳定性专项;最后分出去换成别的产品。每章前面的色点是它主要讲的那一层,颜色和架构图一致。

连接层消息层分发层存储层业务层客户端跨层蓝色标题:已经发布(目前是初稿)

  1. 开篇

    先看整个系统。

    1. 0全景
  2. v0:一台服务器

    1,000 用户

    “App 里要加个聊天。”先做出能用的。

    1. 1最小的聊天
    2. 2从轮询到推送
  3. v1:在手机上不出错

    10 万用户

    移动网络下,消息会丢、会重复、会乱序。

    1. 3确认与重传
    2. 4去重
    3. 5顺序
    4. 6离线同步
    5. 7本地数据库
    6. 8图片与文件
    7. 9v1:一条可靠的通道
  4. v2:群和多端

    10 万用户,500 人的群

    产品要做 500 人的群和桌面端。

    1. 10写扩散还是读扩散
    2. 11入群与退群
    3. 12谁能给谁发消息
    4. 13未读数与已读回执
    5. 14多端同步
    6. 15唤醒离线的手机
    7. 16撤回与编辑
    8. 17会话列表
    9. 18v2:十万用户的群聊
  5. v3:多台服务器

    100 万人同时在线

    一台服务器扛不住,每次发布还会踢掉所有人。

    1. 19拆出网关
    2. 20在线状态
    3. 21百万连接
    4. 22心跳
    5. 23重连风暴
    6. 24账号:App 的用户和 IM 的用户
    7. 25App 的生命周期
    8. 26网页端
    9. 27会话分片
    10. 28写库之前先进队列
    11. 29一套 SDK,多个平台
    12. 30老版本 App,新服务端
    13. 31v3:百万在线
  6. 专项:稳定性

    系统长大以后,难的是一直稳:怎么知道消息真的到了,过载、发布、依赖和机房出故障时怎样不丢、不断。

    1. 32我的消息去哪了?
    2. 33过载:限流与降级
    3. 34发布不断线
    4. 35依赖出故障:隔离与熔断
    5. 36一个机房挂了
    6. 37演练与复盘
  7. 分支:不同的产品

    同一套系统换成 toB、社区、直播、客服、平台,哪些决策会反过来?

    1. 38办公 IM(toB)
    2. 39社区服务器
    3. 40直播间
    4. 41隐私通讯
    5. 42客服
    6. 43IM 作为平台
    7. 44同一个决策,不同的产品

旁支:线路上的细节选读

协议层面的选读。

  1. W1拆包与组帧
  2. W2编码
  3. W3TCP 还是 UDP
  4. W4群组端到端加密