架构实战营 模块 3 作业
前言
本文是游戏开发平台消息队列中间件详细架构设计文档,用于指导后续消息队列的开发、测试和运维。
1. 业务背景
随着游戏业务快速发展,系统越来越多,系统间协作的效率变得很低,主要体现出如下问题:
性能问题:如包管理子系统更新包后需调用 App、Web 等多个子系统,随着通知的子系统增多,影响系统的响应时间,降低系统性能。
耦合问题:如 VIP 子系统判断玩家等级,达到 VIP 后,等级子系统要通知福利子系统进行奖品发放,要通知客服子系统安排专属服务人员,要通知商品子系统进行商品打折处理等,每当新增子系统时,需要改动等级子系统进行接口调用。
效率问题:由于每发布一个接口,都需要调用方和被调方进行开发联调和测试,效率较低。
可用性问题:由于同步调用系统,当被调用系统出现故障,可能导致调用方系统不可用。
基于以上背景,我们需要引入消息队列进行系统解耦,将目前的同步调用改为异步通知。
2. 约束和限制
可用性高,消息不丢失
开发平台采用 Linux,数据库使用 MySQL
只能单机房部署
开发成本不能太高,不超过 1000 万
3. 总体架构
3.1 架构分析
[可选,这部分主要是架构复杂度的分析,基本上从备选架构文档中提炼关键内容过来即可]
3.2 总体架构
消息队列系统采用分片架构,每个分片存储一部分消息数据。
每个分片由消息队列服务器和 MySQL 数据库组成。
一个分片内消息队列服务器设一主一备,MySQL 数据库设一主一备,分片内主备数据复制,分片间数据不同步。
正常情况下分片内主消息服务器对外提供消息读写服务,备服务器不对外提供服务,主服务器宕机的情况下,备服务器对外提供消息读取服务。
客户端采取轮询的策略写入和读取消息
4. 详细设计
4.1 核心功能
4.1.1 消息发送流程
业务服务器中嵌入消息队列系统提供的 SDK,SDK 轮询数据分片发送消息。消息队列服务器接受到消息,则根据消息队列名找到对应的数据表,将消息写入数据表中,写入成功后返回业务服务器。如果写入失败,则 SDK 接收到失败后选择下一个分片重新发起写入请求给该分片的消息服务器。
4.1.2 消息消费流程
业务服务器嵌入消息队列系统提供的 SDK,SDK 轮询数据分片 poll 消息消费。业务服务器通过 SDK 从分片拉取未处理的消息,被拉取的消息置为处理中,并备注当前处理节点、读取消息时间。如果处理成功并提交该消息,则 SDK 通知消息对应的消息服务器将消息置为成功。
4.2 关键设计
4.2.1 消息发送可靠性
业务服务器中嵌入消息队列系统提供的 SDK,SDK 支持轮询发送消息,当某个分组的主服务器无法发送消息时,SDK 挑选下一个分组主服务器重发消息,依次尝试所有主服务器直到发送成功;如果全部主服务器都无法发送,SDK 可以缓存消息,也可以直接丢弃消息,具体策略可以在启动 SDK 的时候通过配置指定。
如果 SDK 缓存了一些消息未发送,此时恰好业务服务器又重启,则所有缓存的消息将永久丢失,这种情况 SDK 不做处理,业务方需要针对某些非常关键的消息自己实现永久存储的功能。
4.2.2 消息存储可靠性
消息存储在 MySQL 中,每个分组有一主一备两台 MySQL 服务器,MySQL 服务器之间复制消息以保证消息存储高可用。如果主备间出现复制延迟,恰好此时 MySQL 主服务器宕机导致数据无法恢复,则部分消息会永久丢失,这种情况不做针对性设计,DBA 需要对主备间的复制延迟进行监控,当复制延迟超过 30 秒的时候需要及时告警并进行处理。
4.2.3 消息如何存储
每个消息队列对应一个 MySQL 表,消息队列名就是表名。
4.3 设计规范
消息队列服务器采用 Spring Boot + Netty 开发
MySQL 使用 Innodb 存储引擎
TCP 包结构采用二进制格式
5. 质量设计
开发消息队列管理子系统,方便监控和运维消息队列,主要提供以下功能:
5.1 可测试性
可以查看队列的消息深度、分片的情况。
可以查看具体消息内容
5.2 可维护性
可创建、删除队列
可定时、手工清理队列
可维护消息状态
可以执行主备切换
可以按需增减分片
5.3 可观测性
可观测消息队列整体情况,如消息总数、消息容量、可用容量等
可观测队列情况,如队列深度
可观测客户端消费情况,如已消费消息笔数、未消费消息笔数
可直观显示出 CPU、内存、磁盘 IO、网络使用量
6. 演进规划
6.1 消息队列一期
保证实现业务的基本需求,提供基本监控和维护功能。
6.2 消息队列二期
完善系统监控,可以实时直观看到系统的运行情况。
系统性能优化。
评论