WhaleShark(鲸鲨)是基于 Netty 实现的高性能分布式 IM 即时通讯系统,它支持对接用户自定义多端登录方式,目前多端登录方式有单端、双端、三端以及无限制
使用到 Netty、Redis、Redisson、RabbitMQ、Zookeeper、RPC、Feign 等主流技术栈
- Netty 实现高性能消息收发,应用层握手(用户登录登出),心跳检测(挂后台)
- Redis 和 Redisson 客户端实现用户 Session 信息的存储、发布订阅模式实现路由层信息缓存
- RabbitMQ 解耦对接 TCP 网关服务和逻辑层交互、保证分布式下消息顺序性
- Zookeeper 注册中心及时感知服务节点上线下线情况
- Feign RPC 方式解耦消息发送方合法性校验
采用 DDD 架构思想搭建各个模块层级,并使用大量设计模式优化架构,使项目易阅读、可扩展
项目树如下
im-system-whale-shark
├─ im-codec 接入层:负责网关服务配置文件集成、私有协议包结构定义、消息编解码以及需要发送给 TCP 服务的数据包定义
├─ im-common 基础层:负责定义整个 IM 架构所有常量、状态码、错误码、基础数据模型
├─ im-domain 领域层:负责定义用户、好友、群组等多个领域的逻辑,以及消息的发送服务
├─ im-message-store 消息存储层:通过 MQ 将消息异步持久化落库, 很薄的一层
├─ im-service 服务层:负责定义底层组件如 redis、zk、mq 的配置逻辑,回调机制和基类消息发送
└─ im-tcp 网关层:负责定义心跳机制、监控用户消息读取以及上线下线、Netty 消息通道以及 WebSocket 全双工通道
- 设计模式重构
- 使用策略模式重构用户操作指令逻辑
- 使用状态模式重构用户自定义多端登录方式
- 使用模板模式重构消息接收器(群聊、单聊的消息接收器逻辑十分相似)
- 使用 Redis 缓存用户信息的方式模拟路由层,实现跨服务之间的多 Channel 通讯
- 使用 Redisson 发布订阅模式,监听用户登录行为,发送用户下线通知。存储用户多端设备的 Session 信息
- 使用 Rabbitmq 处理分布式消息顺序性, 异步执行历史消息落库持久化等问题, 并且解决线上 MQ 消息积压和消息不一致等问题
- 使用拦截器机制, 通过 HMAC-SHA256 加密算法实现接口加密防刷, 提升系统安全性
- 单聊、群聊服务优化改造(实时性、有序性、可靠性、幂等性)
- 实时性: 使用线程池、MQ 异步持久化、RPC 解耦合法性校验大幅提升消息实时性, 接口响应从 400ms 提升至 15ms
- 可靠性: 通过应用层两次握手, 即发送方接收上、下行 ACK 确保消息可靠性, 解决消息丢失问题。消息丢包率从 6.32% 下降到 0
- 有序性: 使用 Redis 原子递增 incr 保证消息有序性, 解决消息乱序问题
- 幂等性: 通过防重 ID, 服务端、客户端缓存消息等幂等性手段遏制消息重复现象, 并限制消息的无限制重试, 接口异常情况从 8.13% 下降到 0
- 实现单聊、群聊消息已读和已读回执功能
- 采用读扩散实现单聊、群聊离线消息拉取
IM 的私有协议确立信息如下:
+------------------------------------------------------+
| 指令 4byte | 协议版本号 4byte | 消息解析类型 4byte |
+------------------------------------------------------+
| 设备类型 4byte | 设备号长度 4byte | 平台ID 4byte |
+------------------------------------------------------+
| 数据长度 4byte | 数据内容(设备号 imei 4byte + 请求体) |
+------------------------------------------------------+
其中请求头共有:7 * 4 byte = 28 byte