第一步 理解问题,确定设计范围
市场主流的聊天应用的侧重有:一对一聊天,群聊,大群互动,低延迟语音聊天(如Discord) 本例设计需求:
- 同时支持一对一与群聊,传输低延迟
- 同时支持移动端和web,可同时登录多设备
- 50 millions DAU
- 群聊最多100人
- 核心功能:一对一,群聊,在线状态,推送通知。简单起见,仅支持文字聊天即可
- 单条消息100k大小限制
- 聊天记录永久保存
- 可暂时不考虑端到端加密
第二步 high-level设计
聊天服务使用的网络协议:
- 轮询
- 长轮询
- webSocket
High-level设计,分为三个部分,分别为:
- 无状态服务(API,用于管理登录注册,用户配置文件等)
- 有状态服务(聊天服务)
- 聊天服务器
- 在线状态服务器
- 第三方集成(通知推送)
存储:采用NoSQL键值存储
一对一聊天:主键为message_id
群聊:复合主键(channel_id,message_id)
message_id的生成方法参考第七章
第三步 深入讨论
服务发现:根据地理位置、服务器容量等标准为客户端推荐最佳的聊天服务器。(Apache Zookeeper是一种流行的服务发现开源解决方案)
消息流:
一对一聊天流程
- 用户A向聊天服务器1发送聊天消息。
- 聊天服务器1从ID生成器获取消息ID。
- 聊天服务器1将消息发送到消息同步队列。
- 消息存储在键值存储中。
- 如果用户B在线,则消息将转发到用户B连接的聊天服务器2。如果用户B离线,则从推送通知服务器发送推送通知。
- 聊天服务器2将消息转发给用户B。用户B和聊天服务器2之间存在持久的WebSocket连接。
多设备消息同步:每个设备都维护一个cur_max_message_id变量。登录时从存储中获取id>cur_max_message_id进行同步
群聊:当群聊人数较小时,可将用户A的消息复制到每个组成员的消息同步队列
在线状态:用户登录,登出,断线会触发状态变更。为防止在线状态频繁变更,可引入心跳机制。
第四步 总结
其它可讨论的点:
- 支持照片和视频等媒体文件
- 端到端加密
- 客户端缓存
- 地理分布式网络来缓存用户的数据、频道,缩短加载时间
- 错误处理
- 聊天服务器错误
- 消息重发机制