“何设计一个类似微信的聊天 App?” 微信作为一个支撑 10 亿+ 用户、日活数亿的超级 App,其架构蕴含的智慧值得每个工程师深入学习。
引言:聊天 App 的复杂度超乎想象
很多人觉得聊天 App 很简单:”不就是发消息吗?”
但当你真正要设计一个日活数亿、消息必达、功能丰富的聊天系统时,会发现它可能是你接触过最复杂的系统之一:
- 实时性:消息延迟要在 200ms 以内
- 可靠性:消息不能丢、不能重复
- 高并发:同时在线用户数千万
- 功能丰富:文字、图片、语音、视频、表情、位置、红包、小程序…
- 跨设备:手机、平板、电脑、Web 多端同步
- 全球化:全球部署、低延迟访问
这已经不是一个”小而美”的系统,而是一个超级分布式系统。
一、需求分析:我们要设计什么?
1.1 核心功能
| 功能 | 描述 | 技术难点 |
|---|---|---|
| 1v1 聊天 | 私聊、消息必达 | 实时推送、离线消息 |
| 群聊 | 多人聊天、满 500 人 | Fan-out 优化 |
| 消息类型 | 文字/图片/语音/视频/表情 | 媒体存储 |
| 已读回执 | 显示”已读” | 状态同步 |
| 在线状态 | 显示”在线/离线” | 心跳管理 |
| 消息撤回 | 撤回消息 | 分布式事务 |
| 朋友圈/状态 | 类似微信朋友圈 | Feed 流设计 |
| 语音/视频通话 | 实时音视频 | WebRTC |
| 消息搜索 | 搜索聊天记录 | 搜索引擎 |
1.2 非功能性需求
flowchart TB
subgraph NFR["非功能性需求"]
Perf["性能
消息延迟 < 200ms"]
Reliability["可靠性
消息不丢不重"]
Scalability["扩展性
支持亿级用户"]
Availability["可用性
99.99% SLA"]
Security["安全性
端到端加密"]
end
- 消息延迟:端到端延迟 < 200ms(同一地域)
- 消息必达:离线消息也要送达,消息不丢失
- 消息不重复:避免重复展示
- 可用性:99.99% SLA,全年故障时间 < 53 分钟
- 扩展性:支持从 1 万到 10 亿用户
- 安全性:端到端加密(E2EE)
二、整体架构设计
2.1 架构总览
flowchart TB
subgraph Client["客户端"]
App["微信/QQ
移动端"]
PC["桌面客户端"]
Web["Web 版本"]
end
subgraph Gateway["接入层"]
LB["负载均衡
L4/L7"]
WSG["WebSocket
Gateway"]
APIG["API
Gateway"]
end
subgraph Service["服务层"]
Msg["消息服务"]
Auth["认证服务"]
Relation["关系服务"]
Profile["用户服务"]
Push["推送服务"]
File["文件服务"]
end
subgraph Storage["存储层"]
Redis["Redis Cluster
缓存/消息队列"]
MySQL["MySQL Cluster
消息/用户"]
HBase["HBase
历史消息"]
ES["Elasticsearch
搜索"]
OSS["对象存储
图片/视频"]
end
subgraph RTC_Sub["实时通信"]
RTC["音视频服务
WebRTC"]
end
App & PC & Web --> LB
LB --> WSG & APIG
WSG & APIG --> Msg & Auth & Relation & Profile & Push & File
Msg & Auth & Relation & Push --> Redis
Msg & Auth & Relation & Profile --> MySQL
Msg --> HBase
Msg --> ES
File --> OSS
App & PC --> RTC
2.2 分层设计
flowchart TD
subgraph ClientLayer ["客户端层"]
direction LR
Client["iOS / Android / Windows / Mac / Web"]
end
subgraph GatewayLayer ["接入层"]
direction LR
LB["负载均衡器 (L4/L7)"]
WSG["WebSocket Gateway"]
APIG["API Gateway"]
end
subgraph ServiceLayer ["业务层"]
direction TB
subgraph ServiceRow1 [" "]
direction LR
Msg["消息服务"]
User["用户服务"]
Relation["关系服务"]
Push["推送服务"]
end
subgraph ServiceRow2 [" "]
direction LR
Group["群服务"]
File["文件服务"]
Call["通话服务"]
Moments["朋友圈"]
end
end
subgraph StorageLayer ["存储层"]
direction TB
subgraph StorageRow1 [" "]
direction LR
Redis["Redis (缓存/消息队列)"]
MySQL["MySQL (业务数据)"]
HBase["HBase (历史消息)"]
ES["ES (搜索)"]
end
OSS["对象存储 (OSS/S3)
图片/语音/视频/文件"]
end
ClientLayer --> GatewayLayer
GatewayLayer --> ServiceLayer
ServiceLayer --> StorageLayer
style ServiceRow1 fill:none,stroke:none
style ServiceRow2 fill:none,stroke:none
style StorageRow1 fill:none,stroke:none
三、核心模块设计
3.1 长连接管理:WebSocket Gateway
聊天系统的核心是长连接——建立一次 TCP 连接,双方可以随时互相发消息。
flowchart LR
subgraph Connection["长连接生命周期"]
Connect["建立连接
WebSocket"]
Auth["认证
Token 验证"]
Register["注册到
路由中心"]
Heartbeat["心跳保活
30秒/次"]
Message["消息收发"]
Disconnect["断开连接
清理状态"]
end
3.2 消息模型设计
1 | // 消息模型 |
消息 ID 生成:使用 Snowflake 算法
1 | # Snowflake: 64 位 ID = 1位符号 + 41位时间戳 + 10位机器ID + 12位序列号 |
3.3 消息发送流程
sequenceDiagram
participant UserA as 用户 A
participant GW as WebSocket Gateway
participant MQ as 消息队列
participant Msg as 消息服务
participant DB as 数据库
participant Redis as Redis
participant GWB as Gateway B
participant UserB as 用户 B
UserA->>GW: 1. 发送消息
GW->>MQ: 2. 写入消息队列
MQ->>Msg: 3. 异步消费
Msg->>DB: 4. 持久化消息
DB-->>Msg: 5. 返回 msgId
Msg->>Redis: 6. 更新消息索引
Msg-->>GW: 7. 返回发送成功
GW->>Redis: 8. 查询用户 B 的 Gateway 地址
Redis-->>GW: 9. 返回 gateway_b
GW->>GWB: 10. 推送消息给用户 B
GWB->>UserB: 11. 实时送达
UserB->>GWB: 12. 发送已读回执
GWB->>DB: 13. 更新消息状态为"已读"
GWB->>GW: 14. 推送已读状态给 A
GW->>UserA: 15. 显示"已读"
3.4 消息存储设计
3.4.1 分表策略
1 | -- 消息表按 receiver_id 分片 |
分片策略:
- 按
receiver_id哈希分片,保证同一用户的消息在同一分片 - 按月/按年归档,历史消息迁移到冷存储
3.4.2 多层存储架构
flowchart TB
subgraph Storage["消息存储层级"]
Hot["热数据
Redis
最近 7 天"]
Warm["温数据
MySQL
7-90 天"]
Cold["冷数据
HBase/OSS
90 天以上"]
end
Hot -->|"访问"| Warm
Warm -->|"归档"| Cold
四、群聊系统设计
4.1 群消息的挑战
群聊和 1v1 聊天完全不同:
| 场景 | 1v1 聊天 | 群聊 (500人) |
|---|---|---|
| 消息分发 | 1 人 | 499 人 |
| Fan-out | 简单 | 复杂 |
| 离线处理 | 1 人 | 499 人 |
4.2 群消息的 Fan-out 策略
flowchart TB
subgraph Fanout["群消息分发"]
Input["用户 A 发送群消息"]
subgraph Sync["同步 Fan-out (小群 <100人)"]
S1["查询成员列表"]
S2["循环推送每个人"]
S3["完成"]
end
subgraph Async["异步 Fan-out (大群 >100人)"]
A1["写入消息队列"]
A2["Fan-out Service 消费"]
A3["并行推送给成员"]
A4["完成"]
end
Input --> S1 & A1
end
优化策略:
1 | # 群消息分发伪代码 |
4.3 群消息的幂等性
1 | # 群消息幂等 Key |
五、在线状态与消息推送
5.1 在线状态管理
flowchart TB
subgraph Online["在线状态流程"]
Connect["建立连接"] --> Heartbeat["心跳
30秒"]
Heartbeat --> Update["更新 Redis"]
Update --> Check{"超时?"}
Check --"是" --> Offline["标记离线"]
Check --"否" --> Continue["保持在线"]
end
5.2 推送服务架构
flowchart LR
subgraph Push["消息推送"]
Msg["消息服务"] --> MQ["消息队列"]
MQ --> PushService["推送服务"]
PushService --> APNS["APNs
Apple"]
PushService --> FCM["FCM
Google"]
PushService --> HMS["HMS
华为"]
PushService --> JPush["极光/个推
国内"]
end
推送策略:
| 状态 | 推送方式 |
|---|---|
| 在线 | WebSocket 实时推送 |
| 离线 | 推送系统 (APNs/FCM) |
| 夜间/勿扰 | 累计通知栏 |
六、消息漫游与多端同步
6.1 多端同步问题
用户在手机、平板、电脑上登录,消息需要实时同步:
sequenceDiagram
participant Phone as 手机
participant PC as 电脑
participant Server as 服务器
Phone->>Server: 1. 发送消息
Server->>Server: 2. 持久化
Server-->>Phone: 3. 确认送达
Server-->>PC: 4. 推送消息给 PC
PC->>Server: 5. 获取完整消息
Server-->>PC: 6. 返回消息内容
6.2 消息漫游实现
1 | # 消息漫游服务 |
七、安全性设计
7.1 端到端加密 (E2EE)
flowchart TB
subgraph E2EE["端到端加密"]
KeyGen["密钥生成
每个设备独立密钥对"]
KeyExchange["密钥交换
Signal Protocol"]
Encrypt["消息加密
发送前加密"]
Decrypt["消息解密
接收后解密"]
end
Signal Protocol 的核心:
1 | # 简化的 E2EE 流程 |
7.2 传输安全
- TLS 1.3:全程 HTTPS/WSS 加密
- 证书固定 (Certificate Pinning):防止中间人攻击
- 设备绑定:敏感操作需要设备验证
八、搜索功能设计
8.1 搜索架构
flowchart TB
subgraph Search["搜索服务"]
Index["索引构建"]
Query["查询服务"]
end
subgraph Engine["搜索引擎"]
ES["Elasticsearch"]
end
subgraph Storage["存储"]
DB["消息数据库"]
end
DB -->|"增量同步"| Index
Index --> ES
Query --> ES
8.2 搜索优化
1 | # 搜索服务 |
九、扩展性与高可用
9.1 多 Region 部署
flowchart TB
subgraph Global["全球部署"]
subgraph CN["中国区"]
CN_GW["Gateway"]
CN_Service["服务"]
CN_DB["数据库"]
end
subgraph US["北美区"]
US_GW["Gateway"]
US_Service["服务"]
US_DB["数据库"]
end
subgraph EU["欧洲区"]
EU_GW["Gateway"]
EU_Service["服务"]
EU_DB["数据库"]
end
end
CN_GW <-->|"专线同步"| US_GW
US_GW <-->|"专线同步"| EU_GW
9.2 容灾与故障转移
| 组件 | 容灾策略 |
|---|---|
| Gateway | 多集群部署,Load Balancer 切换 |
| 消息服务 | 主备切换,消息队列持久化 |
| 数据库 | 主从复制,跨机房部署 |
| 缓存 | Redis Cluster,自动故障转移 |
十、总结
10.1 核心设计原则
- 长连接 + 短轮询结合:WebSocket 保持实时性,HTTP 处理非实时请求
- 消息队列解耦:削峰填谷,保证系统稳定性
- 多层存储架构:热/温/冷数据分层,平衡性能与成本
- 灰度发布:新功能先在小范围验证
- 监控告警:全链路监控,问题早发现
10.2 关键技术选型
| 模块 | 技术选型 | 理由 |
|---|---|---|
| 长连接 | WebSocket | 双向通信,低延迟 |
| 消息队列 | Kafka | 高吞吐,持久化 |
| 缓存 | Redis Cluster | 高性能,丰富数据结构 |
| 消息存储 | MySQL + HBase | 事务 + 大数据 |
| 搜索 | Elasticsearch | 全文搜索 |
| 对象存储 | S3/OSS | 海量文件存储 |
10.3 微信的特殊优化
彩蛋:微信的哪些”神优化”?
- 省电模式:智能心跳,节省电量
- 弱网优化:消息聚合发送,减少请求
- 本地缓存:减少服务器请求
- 增量同步:只同步新增消息
- 通道复用:复用 TCP 连接