转转游戏MQ重构:思考与心得之旅

文章目录

    • 1 背景
      • 1.1 起始之由
      • 1.2 重构前现状
      • 1.3 问题分析
    • 2 重构
      • 2.1 目标
      • 2.2 制定方案
        • 2.2.1 架构设计
        • 2.2.2 实施计划
        • 2.2.3 测试计划
      • 2.3 部分细节设计
    • 3. 总结

1 背景

游戏业务自 2017 年启航,至今已近乎走过七个春秋,历经漫长岁月的发展,不知不觉间背负起沉重的历史包袱。犹如一棵大树,既有繁茂精壮的枝桠,亦有诸多枯败凋零的枝叶。此文主要聚焦于商品更新 MQ 消费这一细微模块,详述游戏业务如何对原有代码予以重构,令游戏这棵大树重焕蓬勃生机。

1.1 起始之由

一日,骤然收到线上对下游接口 RPC 调用限流之警报,限流警报阈值为 600k/min。遂着手排查触发限流警报之因由。追根溯源,发觉乃外部存有更新操作,而更新接口调用阈值大约 3K/min。明明更新流量不高,缘何触发限流?于是开启了对系统的调研与排查。

1.2 重构前现状

经过对限流原因的初步探索,我们进一步对商品消费 MQ 进行了全面梳理,发现游戏已有19个订阅商品更新MQ的Consumer,分布在不同集群。这些Consumer 各自存有内部的查询与更新相关操作,因其部分更新操作会催生新的Message,致使接口调用进一步扩增。

调研还发现有的废弃Consumer还在线上持续消费,有的相同的消费逻辑被多个Consumer在消费。

针对上面问题简单梳理总结,问题如下:
image

a. 逻辑分散,可维护性差
b. 服务调用量成倍放大
c. 存在并发更新和覆盖的情况
d. 存在废弃或者重复消费情况

1.3 问题分析

缘何会产生这些问题?作者认为:前期需求快速迭代,新增新的 Consumer 可迅速响应需求,且开发便捷。然而,伴随需求的演变与迭代,新增的 Consumer 渐多,需求与研发人员的变更,使得系统全貌愈发难以全面掌控。不断变更的逻辑,致使整个系统的维护愈发艰难,从而衍生出形形色色的问题。

若要降低 MQ 相关接口调用量,有两个核心要点:其一,减少查询,实现数据复用;其二,减少更新接口调用,抑制新的 Message 产生。但当下系统已然如此分散,于现有结构上极难获取出色的解决方案。欲改变当前此种状况,需要全新的结构,对原有 MQ 消费逻辑进行重构。借由新的结构,不但能够化解当下的问题,还能够构建新的约束,引导未来新的功能撰写方式,使整个系统更为健康稳定。

2 重构

2.1 目标

在着手重构之前,最为关键的是明晰目标。目标能够辅助我们拟定方案,明确范围,指引项目落地而不偏离正轨。

a. 合理的结构
b. 优化重复无效消费逻辑
c. 提高消费能力
d. 逻辑优化
e. 构建新体系

期望通过合理的代码架构,令消费商品 MQ 消息的逻辑高度内聚且低耦合、各个类及方法的职责清晰明确。重构并非对老系统的简单复制,更肩负着为系统未来扩展定义新的约束规范。恰似于这棵游戏大树中萌生出新的枝干与分支,决定着后续细枝的生长方向。

除了架构合理,还需优化解决此前的重复和无效消费的情况,提升整体消费能力,解决原先接口调用放大的问题。此外,在调研中发现系统存在一些已下线的废弃逻辑和部分有问题的代码,趁此次重构之机予以优化(注:通常不建议在重构中修改逻辑,对于修改逻辑务必要在此环节进行大量测试,否则可能引发一系列系统风险)

2.2 制定方案

重构的总体方案主要由三部分构成:架构设计、实施计划、测试计划

2.2.1 架构设计

image
总体架构主要运用享元设计模式和策略设计模式,整个架构自上而下由三部分组成。

a. 数据预处理
b. 按分类调用Handler进行消费
c. 收拢调用更新接口

a:数据预处理主要负责过滤和预查询数据。包含批量消费 MQ 消息,滤除非游戏的消息,调用批查询接口,预处理后续可能重复处理的逻辑,减少重复查询,提升接口效率。

b:主要是按分类抽取 Handler 和公共 Handler,以使职责清晰分明。抽取公共 Handler 以处理一些公共逻辑,例如记录埋点日志等。各个分类的 Handler 仅处理本分类的业务逻辑,实现逻辑解耦,提升可维护性。为方便切面的使用以及增强相关功能的内聚性,在 Handler 之下额外抽取了一层 Manage 层。Manage 层主要负责实现具体的消费逻辑,并提供可复用组件,令逻辑更具内聚性。

c:对中台商品相关的更新逻辑予以收拢,其主要目的在于减少更新接口的调用。(由于这些更新会产生新的Message,故而通过调用批量接口的方式,来降低更新接口的调用次数,进而有效解决接口调用频率放大的问题)

2.2.2 实施计划

我们将整个重构划分为以下三期来实现。

第一期和第二期

第一期:主要针对非核心业务 MQ 逻辑进行迁移重构。非核心业务灰度上线,控制影响范围,迅速验证架构的可行性与稳定性。

第二期:核心业务相关 MQ 迁移重构。灰度上线,关注对核心业务的影响。完成此步基本完成全部业务逻辑迁移。

第三期

第三期:对结构进行微调,主要是对相关功能进一步拆解、重构,使功能内部更为内聚,降低耦合,令整个系统最终达成设计伊始的预期效果。

分多步进行重构的益处主要在于控制影响范围,能够迅速见到成效。每次改动范围有限,更易于定位问题,也能够极为便利地支持产品需求。

2.2.3 测试计划

每次上线之前,核心主要通过三种测试,即白盒测试、黑盒测试、日志对比。

a:黑盒测试,校验新老流程处理后的数据是否一致。
b:白盒测试。测试每一行代码的覆盖率,并观察新老流程数据是否一致。
c:调用接口前数据对比。在调用更新接口之处打印日志,对比新老流程调用更新接口的传参是否一致。

测试仅是一方面,上线后皆需关注整个系统的运行状况,并做好关键方面的报警。此外,会同步一线客服人员,收集是否存在用户反馈的问题,依照原来Consumer的颗粒度进行灰度。

2.3 部分细节设计

统一幂等灰度切面处理

此系统乃是一个与 MQ 消费相关的重构项目,在每个消费模块皆需确保消费的幂等性,然而迁移而来的Consumer众多,若在每个地方皆书写一遍幂等相关处理,极为不便。我主要借助了 Spring 的 AOP 能力来达成。

幂等实现
主要是定义规范,定义幂等注解、统一返回值(泛型)以及撰写注解处理类。通过环绕注解来实现,处理类在处理之前会进行规范检测,不规范则直接放过(相当于使用注解失效),消费成功后我们会将返回结果通过缓存存储起来,下次再来时,直接消费成功,无需重复处理,达成处理幂等性和减少重复消费的情况。幂等缓存的颗粒度为msgId。(灰度控制方案原理相同,此处不再赘述)

异常失败应对

image
我们在设计下游商品更新时进行了收拢处理,以方便操作,但也带来一个问题,即可能我们的业务信息已更新,而下游可能处理失败,对此我们使用转转封装的基于 RocketMQ 的消费重试组件来实现。(简单来讲,同步消费失败,就会利用 RocketMQ,创建一个MQ消费信息来异步处理)。
未更新成功的数据,通过 MQ 重试来保障消费成功。

更新失败报警

我们还设有报警机制,未更新商品的信息,通过企业微信发送报警,以提示技术人员,并提供商品数据信息,方便在出现特殊异常情况时,人工兜底补足来处理此类情形。

数据隔离

新的Consumer在消费时提供了单独的线程池处理,便于监控逻辑处理消费情况,提升整体逻辑处理能力的并发度。

线程池监控

数据监控

建立丰富的监控指标和报警通知机制。通过日志查询平台、数据看板、异常企业微信报警通知,辅助我们在上线后实时观察新流程的具体状况,迅速定位问题。

MQ生成消费监控

上游查询失败报警

3. 总结

数据效果

项目上线后,下游核心接口的调用量显著降低,降幅 50%至80% 之间。其中,更新类接口的调用量降低了80%,查询类接口的调用量减少了50%。

  1. 明确系统重构的缘由,主要涵盖两方面。(现有系统存在问题需解决,或者现有系统限制了新的业务发展)
  2. 务必要充分了解自身的系统。在重构之前,对于具体的业务逻辑和影响范围等信息需进行直接评估与确定。唯有明晰系统的原貌,方能依据系统的现状设计全新的技术方案。
  3. 考虑未来发展,定义好的规范。好的规范和结构,在未来系统迭代发展起一个引导作用。引导大家按相同的思路开发,更好的协作和支持业务需求。

关于作者

许志芳,转转订单业务研发工程师

转转研发中心及业界小伙伴们的技术学习交流平台,定期分享一线的实战经验及业界前沿的技术话题。
关注公众号「转转技术」(综合性)、「大转转FE」(专注于FE)、「转转QA」(专注于QA),更多干货实践,欢迎交流分享~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/750688.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

应用图扑 HT for Web 搭建拓扑关系图

拓扑结构在计算机网络设计和通信领域中非常重要,因为它描述了网络中的设备(即“点”)如何相互连接(即通过“线”)。这种结构不仅涉及物理布局,即物理拓扑,还可以涉及逻辑或虚拟的连接方式&#…

C++ ─── vector模拟实现的扩容拷贝问题

扩容拷贝问题 源代码使用memcpy拷贝&#xff0c;在使用vector<int>存储内置类型时没有问题&#xff0c; 但是如果存储的是含有指针的类型&#xff0c;如string&#xff0c;就会发生浅拷贝问题 //3、容量相关void reserve(size_t n){if (n > capacity()){size_t old_si…

数字水产养殖中的鱼类追踪、计数和行为分析技术

随着全球人口增长和生态环境退化&#xff0c;传统捕捞已无法满足人类对水产品的需求&#xff0c;水产养殖成为主要的鱼类来源。数字水产养殖利用先进技术和数据驱动方法&#xff0c;对提高生产效率、改善鱼类福利和资源管理具有显著优势。 1 数字水产养殖的重要性 1.1 提高生…

Java web应用性能分析之【prometheus监控指标体系】

Java web应用性能分析之【系统监控工具prometheus】_javaweb服务器性能监控工具-CSDN博客 Java web应用性能分析之【prometheusGrafana监控springboot服务和服务器监控】_grafana 导入 prometheus-CSDN博客 因为篇幅原因&#xff0c;前面没有详细说明Prometheus的监控指标&…

小红书2024LLM论文分享

2024小红书大模型论文分享 BatchEval基于LLM评估LLM生成文本的质量 ACL2024 https://ypw0102.github.io/ 如果文本评价需要多个维度&#xff0c;需要调整BatchEval么&#xff1f; 目前是完整流程走一遍的&#xff0c;因此没有具体考虑细粒度。 评测连续的数据域&#xff0c;S…

使用飞书多维表格实现推送邮件

一、为什么用飞书&#xff1f; 在当今竞争激烈的商业环境中&#xff0c;选择一款高效、智能的办公工具至关重要。了解飞书的朋友应该都知道&#xff0c;飞书的集成能力是很强大的&#xff0c;能够与各种主流的办公软件无缝衔接&#xff0c;实现数据交互&#xff0c;提升工作效…

VAE-pytorch代码

import osimport torch import torch.nn as nn import torch.nn.functional as F from torch.utils.data import DataLoaderfrom torchvision import transforms, datasets from torchvision.utils import save_imagefrom tqdm import tqdmclass VAE(nn.Module): # 定义VAE模型…

基于盲信号处理的声音分离-基于改进的信息最大化的ICA算法

基于信息最大化的ICA算法的主要依据是使输入端与输出端的互信息达到最大&#xff0c;且输出各个分量之间的相关性最小化&#xff0c;即输出各个分量之间互信息量最小化&#xff0c;其算法的系统框图如图所示。 基于信息最大化的ICA算法的主要依据是使输入端与输出端的互信息达到…

java基于ssm+jsp 弹幕视频网站

1前台首页功能模块 弹幕视频网站&#xff0c;在弹幕视频网站可以查看首页、视频信息、商品信息、论坛信息、我的、跳转到后台、购物车、客服等内容&#xff0c;如图1所示。 图1前台首页界面图 登录&#xff0c;通过登录填写账号、密码等信息进行登录操作&#xff0c;如图2所示…

Sparse4D v1

Sparse4D: Multi-view 3D Object Detection with Sparse Spatial-Temporal Fusion 单位&#xff1a;地平线 GitHub&#xff1a;https://github.com/HorizonRobotics/Sparse4D 论文&#xff1a;https://arxiv.org/abs/2211.10581 时间&#xff1a;2022-11 找博主项目讨论方…

【MotionCap】conda 链接缺失的cuda库

conda 安装的环境不知道为啥python 环境里的 一些cuda库是空的要自己链接过去。ln 前面是已有的,后面是要新创建的 ln -s <path to the file/folder to be linked> cuda 有安装 libcublas 已经在cuda中 (base) zhangbin@ubuntu-server:~/miniconda3/envs/ai-mocap/lib/…

ARM芯片架构(RTOS)

前言&#xff1a;笔记韦东山老师的rtos教程&#xff0c;连接放在最后 #ARM介绍 arm芯片属于精简指令集risc&#xff0c;所用的指令比较简单&#xff0c;ARM架构是一种精简指令集&#xff08;RISC&#xff09;架构&#xff0c;广泛应用于移动设备、嵌入式系统、物联网等领域。AR…

40.设计HOOK引擎的好处

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 上一个内容&#xff1a;39.右键弹出菜单管理游戏列表 以 39.右键弹出菜单管理游戏列表 它的代码为基础进行修改 效果图&#xff1a; 实现步骤&#xff1a; 首…

吴恩达2022机器学习专项课程C2W3:2.27 选修_数据倾斜

目录 处理不平衡数据集1.分类需求描述2.计算精确率和召回率 权衡精确率和召唤率1.手动调整阈值2.F1分数 总结 处理不平衡数据集 1.分类需求描述 如果你在处理一个机器学习应用&#xff0c;其中正例和负例的比例&#xff08;用于解决分类问题&#xff09;非常不平衡&#xff0…

图像大小调整(缩放)

尺寸调整前尺寸调整前 1、背景介绍 在深度学习中&#xff0c;将图像调整到固定尺寸&#xff08;如28x28像素&#xff09;的操作是非常常见的&#xff0c;尤其是在处理诸如图像分类、物体检测和图像分割等任务时。这种操作有几个重要原因&#xff1a; 标准化输入&#xff1a;许…

MYSQL 四、mysql进阶 5(InnoDB数据存储结构)

一、数据库的存储结构&#xff1a;页 索引结构给我们提供了高效的索引方式&#xff0c;不过索引信息以及数据记录都是保存在文件上的&#xff0c;确切说时存储在页结构中&#xff0c;另一方面&#xff0c;索引是在存储引擎中实现的&#xff0c;Mysql服务器上的存储引擎负责对表…

当中年男人的觉越来越少 他突然半夜买台电脑(30+岁仿真工程师买电脑心得)

仿真工程师的购机分析&#xff0c;游戏本、移动工作站还是台式机&#xff1f; 认清自己的需求。 现状。现在有一个19年买的华为matebook14、i5第八代低压U&#xff0c;8G内存。还好有SSD当虚拟内存&#xff0c;要不开网页估计都得卡住。媳妇还有台i7、16G的matebook&#xff…

MC进样管PFA塑料管NEPTUNE Plus多接收等离子质谱仪配套管子

PFA进样管可适配Neptune plus多接收器等离子质谱仪&#xff08;MC-ICP-MS&#xff09;&#xff0c;广泛应用于地球化学、核保障、环境科学、金属组学领域&#xff0c;在生物、物理、化学、材料等多个学科的交叉方向也有良好的应用前景。 外观半透明&#xff0c;便于观察管内情…

基于LangChain构建RAG应用

前言 Hello&#xff0c;大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者&#xff0c;上一篇文章中我们详细介绍了RAG的核心思想以及搭建向量数据库的完整过程&#xff1b;&#x1f632; 本文将基于上一篇文章的结果进行开发&#xff0c;主…

最长回文串

描述&#xff1a; 最长回文串 思路&#xff1a; 统计每个字母出现次数&#xff0c;如果是偶数&#xff0c;ret x;如果是存在奇数的话&#xff0c;就可以放在中间&#xff0c;ret 1. 代码&#xff1a; class Solution { public:int hash[200];int longestPalindrome(str…