消息队列架构设计文档
前言
本文是游戏业务线消息队列中间件详细架构设计文档,用于指导消息队列后续的开发、测试和运维。
词汇表
Reactor: 网络编程模式
Netty: 开源的网络编程框架
ISO 27701: 隐私信息管理体系认证
1. 业务背景
游戏业务发展很快,系统也越来越多,系统间协作的效率很低,例如:
- 效率问题:玩家进行充值,充值完成后充值子系统通知 VIP 子系统; VIP 子系统判断玩家等级,达到 VIP 后,等级子系统要通知福利子系统进行奖品发放,要通知客服子系统安排专属服务人员,要通知商品子系统进行商品打折处理……等级子系统的开发人员也是不胜其烦。 
- 耦合问题:各个子系统之间的相互调用,增大了系统的耦合性。 
基于以上背景,我们亟需引入消息队列进行系统解耦,将目前的同步调用改为异步通知。而综合分析各开源消息队列以及阿里内部的消息队列,最终决定采用自研消息队列的方案。
以下系统边界黑盒图来描述系统与外界的边界和交互关系:
 
 2. 约束和限制
- 投资方的成本要求:不超过 100 万 
- 监管方的监管要求:符合 ISO 27701 标准 
- 技术选型的硬性要求:使用 MySQL 作为数据存储 
- 项目时间要求:不得超过 3 个月 
- 质量要求:符合 ISO 27701 标准 
3. 总体架构
3.1 架构分析
3.1.1 可维护性
- 方案可以融入到现有的运维体系中,而且使用 MySQL 存储数据,可靠性有保证,运维团 队也有丰富的 MySQL 运维经验 
- 对业务团队 来说,只要保证消息队列系统稳定和可靠即可 
3.1.2 业务场景
可以为业务场景定制开发各种特性,例如:
- 权限控制 
- 费速度预警 
等等。
3.1.3 性能
部分研发人员对于这个方案的性能持怀疑态度,毕竟使用 MySQL 来存储消息数据,性能肯定不如使用文件系统。但综合分析性能不成问题:
- 每个消息队列对应一个表 
- 消息表最多存储 30 天内的消息,过期的自动清除 
- 消息队列还通过分片(sharding)来减小 MySQL 服务器的压力 
- MySQL 的 TPS 达到 1000 没问题 
3.2 总体架构
系统边界白盒图描述系统内的角色与外界的交互(Rank + Role + 外部 Relation):
 
 系统架构图来描述内部的 Role + 内部 Relation:
 
 - 客户端 Role 设计 
- 客户端采用 Java 语言开发,基于 Netty 实现与服务端交互 
- 服务器 Role 设计 
- 服务器基于 Netty 开发,采用 Reactor 网络模型 
- 两台服务器组成一个 sharding,整个系统可以多个 sharding,每个 sharding 包含一主一从两台服务器(可以对比 MongoDB shard) 
- 主服务器提供消息读写操作,从服务器只提供消息读取操作 
- 服务器基于 ZooKeeper 进行主从切换 
- 客户端和服务器的 Relation 设计 
- 客户端与服务端采用 TCP 连接,采用 Json 传递数据 
- 为了兼容非 Java 系统,服务端同时提供 HTTP 接口 
- MySQL 的 Role 和 Relation 设计 
- 采用 MySQL 主从同步 
- 每个消息队列对应一个表 
- 消息表最多存储 30 天内的消息,过期的自动清除 
- 直接用 MySQL 的主从复制来实现数据复制 
4. 详细设计
4.1 核心功能
4.1.1 消息发送流程
 
 - 消息队列系统涉及两个角色:生产者和消费者,每个角色都有唯一的名称 
- 消息队列系统提供 SDK 供各业务系统调用,SDK 从配置中读取所有消息队列系统的服务器信息,SDK 采取轮询算法发起消息写入请求给 主服务器 
- 如果某个主服务器无响应或者返回错误,SDK 将发起请求发送到下一台主服务,相当于在客户端实现了分片的功能 
4.1.2 消息消费流程
 
 - 消息队列系统涉及两个角色:生产者和消费者,每个角色都有唯一的名称 
- 消息队列系统提供 SDK 供各业务系统调用,SDK 从配置中读取所有消息队列系统的服务器信息,轮流向所有服务器发起消息读取请求 
- 消息队列服务器需要记录每个消费者的消费状态,即当前消费者已经读取到了哪条消息,当收到消息读取请求时,返回下一条未被读 取的消息给消费者 
- 默认情况下主服务器提供读写服务,当主服务器挂掉后,从服务器提供读消息服务 
4.2 关键设计
- 服务器主从切换 
- 同一组的主从服务器配置相同的 group 名称,在 ZooKeeper 建立对应的 PERSISENT 节点 
- 主从服务器启动后,在 ZooKeeper 对应的 group 节点下建立 EPHEMERAL 节点,名称分为为 master 和 slave 
- 从服务器 watch 主服务器的 master 节点状态,当 master 节点超时被删除后,从服务器接管读消息,收到客户端 SDK 的读消息请求后返回 消息,收到客户端 SDK 的写请求直接拒绝 
4.3 设计规范
- 消息队列服务器使用 Spring Boot + Netty 开发 
- MySQL 使用 Innodb 存储引擎 
- TCP 包的结构设计采用 JSON 明文格式 
- 需要支持 HTTP 接口 
5. 质量设计
5.1 可测试性
- 可在消息队列管理系统: 
- 查看消息、队列和分片 
- 消费消息 
- 查看消息 
- 修改消息状态 
- 主备倒换 
- 主备切换 
- 增减分片 
5.2 可维护性
- 可在消息队列管理系统: 
- 查看消息、队列和分片 
- 修改消息状态 
- 消费消息 
- 关闭分片 
- 增减分片 
- 关闭队列 
5.3 可观测性
- 可在消息队列管理系统: 
- 查看消息、队列和分片 
5.4 成本
- 第一版采用两个分片 
- 如果效率不足,增加分片 
6. 演进规划
6.1 消息队列一期
- 本文内容 
- 如果 deadline 无法保证 
- 简化权限管理 
- 简化监控 
- 简化维护 
6.2 消息队列二期
- 完善消息队列管理系统 
- 优化消息队列管理系统 
6.3 消息队列三期
- 尝试用 HBase 替换 MySQL 
- 制作内部测试版 
6.4 消息队列四期
- 如果用 HBase 替换 MySQL 效果明显 
- 制作最终生成版 












 
    
评论