一条消息从 Ana 的手机到 Ben 的手机,中间要经过什么?
一步步设计一个 IM 系统:从一台服务器到百万人同时在线,每一章只做一个设计决策。服务端和客户端都讲,中文和英文都有。
IM 只做两件事:可靠地收下每一条消息,再把它送到每一台设备,包括离线后回来的那台。
图中没画:音视频通话、端到端加密、多机房容灾、合规留存、搜索。
- 发送:Ana 的消息经长连接进入 IM
- 存好就回复“已发送”(不是“已送达”),Ana 不再等后面的事
- 推送到 Ben 在线的设备;离线时发系统通知,只是提醒
- 任何错过消息的设备,回来后自己拉取补齐
点任意一层,看它做什么、难在哪、在哪几章深入讲。
目前写到:开篇(第 0 章)初稿。
每一章都按这个顺序走
- 问题一个具体场景,比如“同一条消息出现了两次”。
- 看它坏掉在页面里的模拟器上跑简单方案。
- 估算一个纸笔就能核对的数字,说明为什么会坏。
- 修好它在同一个模拟器里打开修复,对比前后。
- 代价修复要付出什么,别的产品会怎么选。
为什么写这个
讲 IM 架构的文章很多,但大多只给一张最终的架构图,或者讲某一家公司的历史。很少有人一步步讲清楚:一个系统为什么会长成这样。
这里跟着一个聊天 App 从 1,000 个用户长到 100 万人同时在线。系统的四层和旁路的业务层一开始挤在一个程序里,每一次增长都逼着其中一部分被拆出来、做深。
最后几章换成 toB 办公、社区、直播、隐私通讯、客服,以及给别的业务用的 IM 平台,看同样的决策怎样反过来。架构没有唯一正确的答案,产品决定答案。
章节地图
主干跟着一个 App 从 v0 长到 v3,每一站写着它的规模和为什么要长大;然后是稳定性专项;最后分出去换成别的产品。每章前面的色点是它主要讲的那一层,颜色和架构图一致。
连接层消息层分发层存储层业务层客户端跨层蓝色标题:已经发布(目前是初稿)
开篇
先看整个系统。
- 0全景
v0:一台服务器
1,000 用户
“App 里要加个聊天。”先做出能用的。
- 1最小的聊天
- 2从轮询到推送
v1:在手机上不出错
10 万用户
移动网络下,消息会丢、会重复、会乱序。
- 3确认与重传
- 4去重
- 5顺序
- 6离线同步
- 7本地数据库
- 8图片与文件
- 9v1:一条可靠的通道
v2:群和多端
10 万用户,500 人的群
产品要做 500 人的群和桌面端。
- 10写扩散还是读扩散
- 11入群与退群
- 12谁能给谁发消息
- 13未读数与已读回执
- 14多端同步
- 15唤醒离线的手机
- 16撤回与编辑
- 17会话列表
- 18v2:十万用户的群聊
v3:多台服务器
100 万人同时在线
一台服务器扛不住,每次发布还会踢掉所有人。
- 19拆出网关
- 20在线状态
- 21百万连接
- 22心跳
- 23重连风暴
- 24账号:App 的用户和 IM 的用户
- 25App 的生命周期
- 26网页端
- 27会话分片
- 28写库之前先进队列
- 29一套 SDK,多个平台
- 30老版本 App,新服务端
- 31v3:百万在线
专项:稳定性
系统长大以后,难的是一直稳:怎么知道消息真的到了,过载、发布、依赖和机房出故障时怎样不丢、不断。
- 32我的消息去哪了?
- 33过载:限流与降级
- 34发布不断线
- 35依赖出故障:隔离与熔断
- 36一个机房挂了
- 37演练与复盘
分支:不同的产品
同一套系统换成 toB、社区、直播、客服、平台,哪些决策会反过来?
- 38办公 IM(toB)
- 39社区服务器
- 40直播间
- 41隐私通讯
- 42客服
- 43IM 作为平台
- 44同一个决策,不同的产品
旁支:线路上的细节选读
协议层面的选读。
- W1拆包与组帧
- W2编码
- W3TCP 还是 UDP
- W4群组端到端加密