写点什么

架构实战营 模块 3 作业

用户头像
李晶晶
关注
发布于: 2021 年 05 月 09 日

游戏业务消息队列中间件详细架构设计文档

前言

本文是游戏业务消息队列中间件详细架构设计文档,用于指导消息队列后续的开发、测试和运维。

词汇表

Reactor:网络编程模式

Netty:开源的网络编程框架

Shard:数据分片,将数据拆分的一种技术

Zookeeper:分布式服务协调中间件,用于主备切换

 

1. 业务背景

游戏业务发展很快,系统也越来越复杂,目前系统间的调用都是同步调用,由此带来几个明显的系统问题:

性能问题:当有新的游戏版本发布时,运营管理子系统需依次通知“论坛”、“包管理子系统”、“app”和“web”等子系统,性能较低(如图一);

耦合问题:各个系统之间是高内聚低耦合,比如游戏充值业务,充值子系统需要调用 vip 子系统,vip 子系统调用等级子系统,子系统继续调用客服子系统,客户子系统再通知商品子系统(如图二);

效率问题:每个子系统提供的接口参数和实现都有一定细微的差别,导致每次都需要重新设计接口和联调接口,开发团队和测试团队花费了许多重复工作量。

基于以上背景,我们需要引入消息队列进行系统解耦,将目前的同步调用改成异步通知,提高耦合度。

图一:游戏版本发布系统边界黑盒图

图二:充值服务系统边界黑盒图

2. 约束和限制

1)必须在 2021.07.30 号完成

2)成本不能超过 500 万

3)数据库采用 mysql

3. 总体架构

消息队列系统主要分为客户端 sdk 和服务端两部分,业务系统集成客户端 sdk,通过客户端 sdk 对消息队列服务端进行读写操作完成业务逻辑,从而有效解耦了各个业务系统,如图三。

图三:消息队列系统边界白盒图

消息队列服务端有包含服务程序 httpServer、存储 mysql、主备切换 zookepper 三部分,如图四。其中 httpServer 采用分组部署的方式实现高可用,每组分为主备两台机器,通过 zookeeper 实现主备切换,每组 httpServer 采用一组主备的 msyql 进行存储确保数据高可用,mysql 主备之间通过 binlog 方式实现数据同步。

图四:消息队列框架图

3.1 架构分析

3.1.1 高可用

对于游戏版本发布和登记子系统来说,都是高优先级业务,若出现不可用将导致用户流失从而损失收入。

3.1.2 高性能

因为消息新版本发布、VIP 充值业务不是很频繁,所以不需要考虑高性能。

3.1.3 可扩展

当前消息队列的功能基本明确,无需扩展。

3.2 总体架构

    消息队列系统整体架构图如图五,主要内容说明如下:

1)消息队列系统主要由客户端 sdk 和服务端 httpServer 组成,客户端 sdk 和 httpServer 基于 java 语言开发;

2)使用 netty 自定义消息格式,并且支持 http 接口;

3)消息存储采用 mysql;

4)采用数据分散集群的架构,及集群的服务器进行分组,每个分组分为主备两台服务器,每个分组存储一部分的消息数据,根据消息队列的 id 的 hash 进行分组,每个消息队列存储在其中的一个分组上;

5)每个分组包含一台主 mysql 和一台备 mysql,分组内主备数据复制,分组间数据不同步;

6)正常情况下,分组内的主服务器对外提供消息写入和消息读取服务,备服务器不对外提供服务;

7)主服务器宕机的情况下,备服务器对外提供消息读取的服务,获取到的客户端写入请求将被拒绝;

8)客户端 sdk 采用轮询的策略写入和读取消息;

9)每组主备服务器之间基于 zookeeper 实现主备切换。


图五:消息队列整体架构图

4. 详细设计

消息队列系统角色主要有生产者和消费者,核心功能主要为消息发送、消息消费、消息存储以及服务主备切换三个模块。

4.1 核心功能

4.1.1 消息发送流程

(1)消息队列系统设计两个角色:生产者和消费者,每个角色都有唯一的名称;

(2)消息队列系统提供 sdk 供各业务系统调用,sdk 从配置中读取所有消息队列系统的服务器信息,sdk 采取轮询算法发起消息写入请求到主服务器;

(3)如果某个主服务器无响应或者返回错误,sdk 将发起请求发送到下一台主服务器,相当于在客户端实现了分片的功能;

4.1.2 消息消费流程

(1)消息队列系统提供 sdk 供各业务系统调用,sdk 从配置中读取所有消息队列系统的服务器消息,轮流向所有服务器发起消息读取请求。

(2)消息队列服务器需要记录每个消费者的消费状态,即当前消费者已经读取到了哪条消息,当收到消息读取请求时,返回下一条未被读取的消息给消费者。

4.1.3 服务器主从切换

(1)同一组的主从服务器配置相同的 group 名称,在 zookeeper 建立对应的 persisent 节点

(2)主从服务器启动后,在 zookeeper 对应的 group 节点下建立 ephemeral 节点,名称分别为 master 和 slave;

(3)从服务器 watch 主服务器的 master 节点状态,当 master 节点超时被删除后,从服务器接管读消息,收到客户端 sdk 的读请求消息后返回消息,收到客户端 sdk 的写强求直接拒绝。

4.2 关键设计

4.2.1 消息发送可靠性

1)业务服务嵌入消息队列系统提供的 sdk,sdk 支持轮询发送消息,当某个分组的主服

务器无法发送消息时,sdk 挑选下一个分组主服务器重发消息,依次尝试所有主服务器直到发送成功;

2)如果全部主服务器都无法发送,sdk 可以通过配置消息策略来处理消息,比如消息

丢弃,消息存入客户端缓存里,消息存入持久化数据库里,比如 redis 或者 mysql。

4.2.2 消息存储可靠性

1)消息存储在 mysql 中,每个分组有一主一备两台 mysql 服务器,mysql 服务器之间复制消息以保证消息存储高可用;

2)对 mysql 主从复制延迟进行监控,当复制延迟超过 30s 的时候产生告警并进行运维手工干预处理;

3)当 mysql 主从复制发生延迟且在 30s 内,恰好此时 mysql 主服务器宕机导致数据无法恢复,这种情况可接受。

4.2.3 消息及消息状态存储

1)每个消息队列对应一个 mysql 表,消息队列名就是表名,表设计结构设计如下:

2)每个消息队列消费情况对应一个 mysql 表,表名为“消息队列名_consumeinfo”,

表设计结果如下:

3)消息按月进行清理,以 collectTime 为判断,每月清理一个月以前的消息。

4.3 设计规范

1)消息队列服务器采用 springboot + netty 开发;

2)消息队列 sdk 采用 java 开发;

3)Mysql 使用 innodb 存储引擎;

4)Zookeeper 采用三节点集群部署方式;

5)tcp 包的结构设计为:crc(int32 消息完整性校验)+magincByte(int8 消息版本性兼容标识,默认为 0)+attributes(int8 消息的元数据信息,最后低两位标识消息是否压缩存储以及压缩方式)+value(bytes,消息具体内容)。

5. 质量设计

5.1 消息队列管理后台

消息队列管理后台包含权限管理、配置管理、监控和维护四个模块,如图六。

权限管理是针对各个业务系统对消息队列表的读写权限管理;配置管理是维护消息队列服务器信息、以及每组消息队列服务器维护的消息队列表信息;监控主要是通过 prometheus 监控 sdk、消息队列服务器、mysql、zookeeper 等组件运行情况;维护是指通过发送命令的方式管理消息队列服务器。

图六:消息队列管理系统模块图

5.2 成本

中间件研发团队投入较低,实现成本低;

测试需要投入一定的人力,对消息队列服务器、mysql 高可用进行测试;

运维团队来说运维成本会较高,需要的硬件较多,需要 8-12 台服务器。

6. 演进规划

6.1 消息队列一期

    一期完成客户端 sdk、消息队列服务端(单点)、消息队列管理系统(配置管理、权限管理)开发。

6.2 消息队列二期

    二期完成消息队列服务器高可用、消息队列管理系统(监控、维护)开发。

 

用户头像

李晶晶

关注

还未添加个人签名 2018.08.21 加入

还未添加个人简介

评论

发布
暂无评论
架构实战营 模块3作业