项目迭代中新老逻辑切流和对比 - 异步查询新接口

  1. 项目迭代中新老逻辑切流-切换入口
  2. 项目迭代中新老逻辑切流 - 异步查询新接口
  3. 项目迭代中新老逻辑切流 - 新老数据对比—待更新

前言

前面说到了 项目迭代中新老逻辑切换入口 ,有兴趣的可以先看一下,不知道大家有什么疑问吗?

  • 怎么知道自己新接口逻辑对不对?

  • 怎么知道自己新接口返回的数据对不对?

  • 能否兼容老逻辑?

  • 能否对上游调用方无感知呢?

答案只有一个:新老接口的返回数据永远保持一致!

所以我们前面文章说的切流还差下面的两步操作:

  • 在查询老接口的通知查询新接口
  • 将查询的新接口数据和老接口数据进行对比

一旦发现对比期间不一致的情况,就要排查问题,然后修改新逻辑问题。只有当所有的结果都一致是才能安心的切换到新逻辑里面,晚上才能睡个好觉。

正文

首先我们需要在原先的 MapperSwitchHandler 中添加线程池配置,用来执行新逻辑的异步操作,目的是不阻塞原方法的执行。

@Slf4j
@Getter
@Component
public class MapperSwitchHandler {@Resourceprivate NewARepository newARepository;@Resourceprivate NewBRepository newARepository;//添加的线程池配置(需要提前配置)@Resourceprivate ThreadPoolTaskExecutor threadPoolTaskExecutor;//lombok忽略此属性,不生成 get 方法@Getter(AccessLevel.NONE)//获取 apollo 配置信息@ApolloJsonValue(namespace = "namespace", config = "config", key = "key")private JSONObject mapperSwitch;/*** @Author: zhou* @Description: 根据传入参数获取 apollo 配置的 boolean 值* @Date: 2024/5/27 11:38* @Param: className apollo 中类名--一级* @Param: methodName apollo 中方法名--二级* @return: boolean*/private boolean switchResult(String className, String methodName) {if (mapperSwitch == null) {return false;}return Optional.ofNullable(mapperSwitch.getJSONObject(className)).map(item -> item.getBoolean(methodName)).orElse(false);}/*** @Author: zhou* @Description: 根据 apollo 配置的 boolean 值来判断是否执行传入的 action 函数,并获取结果* @Date: 2024/5/27 11:36* @Param: className apollo 中类名* @Param: methodName apollo 中方法名* @Param: action 待执行函数* @return: MapperSwitchHandler.Result<T>*/public <T> Result<T> switchHandler(String className, String methodName, Supplier action) {Result<T> result = new Result<>();boolean flag = switchResult(className, methodName);log.info("className:{}, methodName:{}, mapper switch : {}", className, methodName, flag);result.setFlag(flag);if (result.isFlag()) {result.setData((T) action.get());log.info("new logic result :{}", JSONObject.toJSONString(result.getData()));} else {log.info("old logic start...");}return result;}@Slf4j@Datapublic static class Result<T> {/*** 逻辑标识*/private boolean flag;/*** 获取的结果*/private T data;}
}

我们用前文的 Repository 的基础上继续改造,下面是改造前的代码,请和改造后的代码进行对比。

@Service
public class ARepository {@Resourceprivate AMapper aMapper;//注入开关@Resourceprivate MapperSwitchHandler mapperSwitchHandler;public AEntity query(long id) {MapperSwitchHandler.Result<AEntity> result = mapperSwitchHandler.switchHandler("ARepository","query",() -> mapperSwitchHandler.getNewARepository().query(id));// flag 判断是否走新 sql ,true 标识走新 sql,直接返回;false 标识走老逻辑if (result.isFlag()) {return result.getData();}//原有的接口逻辑处理AEntity entity = aMapper.query(id);return entity;}
}

我们要在这个代码的基础上添加异步代码,让程序能够在切流之前执行老逻辑的同时执行新逻辑,同时拿到新老结果。

@Service
public class ARepository {@Resourceprivate AMapper aMapper;//注入开关@Resourceprivate MapperSwitchHandler mapperSwitchHandler;public AEntity query(long id) {Supplier<AEntity> supplier = () -> mapperSwitchHandler.getNewARepository().query(id);MapperSwitchHandler.Result<AEntity> result = mapperSwitchHandler.switchHandler("ARepository","query",supplier);// flag 判断是否走新 sql ,true 标识走新 sql,直接返回;false 标识走老逻辑if (result.isFlag()) {return result.getData();}//原有的接口逻辑处理AEntity entity = aMapper.query(id);//下面是异步操作,不影响老逻辑接口返回mapperSwitchHandler.getThreadPoolTaskExecutor().submit(() -> {AEntity newAEntityResult = supplier.get();//我们在这里对比老数据 entity 和 newAEntityResult 的数据是否一致,下面的对比逻辑肯定是不对的,下节介绍if (!newAEntityResult.equals(entity)) {System.out.println("老数据:" + JSONObject.toJSONString(entity) + "\r\n" +"新数据:" + JSONObject.toJSONString(newAEntityResult) + "\r\n");throw new RuntimeException("数据不一致,请检查");}});return entity;}
}

这样我们就能够在执行老逻辑的同时执行新逻辑,同时拿到两个数据之后进行数据对比,以此来确认新接口的数据是否正确。

尾言

在上一节介绍了日常工作中对项目进行迭代是新老逻辑接口的切换办法和思路,这一章介绍了在切换之间,对新老逻辑的返回数据的收集,以便于分析和对比,以对比结果来决定是否需要进行新接口切流。

在下一章,就说一说如何对于新老数据做对比,以及收集、排错等办法。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

红海云签约海新域集团,产业服务运营领军企业加速人力资源数字化转型

北京海新域城市更新集团有限公司&#xff08;以下简称“海新域集团”&#xff09;是北京市海淀国有资产投资集团有限公司一级监管企业&#xff0c;致力于成为国内领先的产业服务运营商。集团积极探索城市和产业升级新模式&#xff0c;通过对老旧、低效等空间载体重新定位规划、…

FPGA基本资源介绍

文章目录 FPGA资源介绍1.可编程输入输出单元(IOB)2.可配置逻辑块(CLB)3.数字时钟管理模块(DCM)4.嵌入式块RAM(BLOCK RAM / BRAM)4.1其他ram 5.丰富的布线资源6.底层内嵌功能单元7.内嵌专用硬核软核、硬核、以及固核的概念 FPGA资源介绍 1.可编程输入输出单元(IOB) 可编程输入…

C++视觉开发 五.答题卡识别

答题卡识别主要步骤 (1)反二值化&#xff0c;选项处理为前景&#xff08;白色&#xff09;&#xff0c;其它处理为背景&#xff08;黑色&#xff09;。 (2)每个选项提取出来&#xff0c;计算各选项白色像素点个数。 (3)筛选出白色像素点最多的选项作为考生答案。 (4)与标准答案…

【机器学习】连续字段的特征变换

介绍 除了离散变量的重编码外&#xff0c;有的时候我们也需要对连续变量进行转化&#xff0c;以提升模型表现或模型训练效率。在之前的内容中我们曾介绍了关于连续变量标准化和归一化的相关内容&#xff0c;对连续变量而言&#xff0c;标准化可以消除量纲影响并且加快梯度下降…

微信扫码进入小程序的webview页面,发现左上角没有home键

问题描述&#xff1a; 微信扫小程序二维码进到web-view内嵌h5页面&#xff0c;左上角没有返回小程序主页的home键&#xff0c;ios正常显示&#xff0c;Android 没有显示 导致的原因&#xff1a; 因为顶部导航栏我是自定义的 【如果是使用小程序原生的顶部导航栏是不会出现这种…

DiffSynth-Studio全面解析与应用示例

DiffSynth-Studio简介 1.1 DiffSynth-Studio的定义与目标用户 DiffSynth-Studio 是一个创新的扩散引擎&#xff0c;专门设计用于实现图片和视频的风格转换。它通过先进的机器学习技术&#xff0c;为用户提供了一种全新的创作方式&#xff0c;使得风格转换变得更加高效和直观。…

latex中引用参考文献的命令

在LaTeX中&#xff0c;常用于引用参考文献的命令有几种&#xff0c;它们的区别主要在于引用的风格和输出的格式。以下是几种常见的引用命令及其区别&#xff1a; 命令输出效果区别与特点\cite{key}[1]基本的引用命令&#xff0c;输出带方括号的引用编号\citet{key}Author (Yea…

循环序列模型

循环序列模型 1.为什么选择序列模型&#xff1f; 2.数学符号 3.循环神经网络模型 4.通过时间的反向传播 5.不同类型的循环神经网络 6.语言模型和序列生成 7.对新序列采样 8.循环神经网络的梯度消失 9.GRU单元 10.长短期记忆 11.双向循环神经网络 12.深层循环神经网…

年化达21%(K=1),最大回撤35%,K=3时,卡玛比最优,最大回撤20%(年化15.2%)| Quantlab5.0代码发布

原创文章第578篇&#xff0c;专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 Quantlab5.0代码发布&#xff1a; 值得说明&#xff0c;Quantlab5与4没有继承关系&#xff0c;5开始的思路是&#xff1a; 1、尽量少封装&#xff0c;保留回测框架最原始的功能。…

【LabView学习篇 - 1】:初始LabView

文章目录 初始LabView前面板和程序框图前面板&#xff08;Front Panel&#xff09;程序框图&#xff08;Block Diagram&#xff09;交互和工作流程 练手小案例&#xff1a;LabView中实现加法操作 初始LabView LabVIEW&#xff08;Laboratory Virtual Instrument Engineering W…

C#的多线程UI窗体控件显示方案

在C#中&#xff0c;特别是在使用Windows窗体&#xff08;WinForms&#xff09;或WPF&#xff08;Windows Presentation Foundation&#xff09;进行UI开发时&#xff0c;处理多线程与UI控件的交互需要特别小心。由于UI控件不是线程安全的&#xff0c;直接从非UI线程&#xff08…

yolov5 训练过程中的监控指标说明

1、参数的具体含义及其重要性 epoch: 训练迭代次数&#xff0c;表示模型已经进行了多少轮的训练。这是模型训练的基本计数单位&#xff0c;对于跟踪训练进度至关重要。 train/box_loss: 训练过程中边界框&#xff08;bounding box&#xff09;预测的损失值。这反映了模型在定位…

【CT】LeetCode手撕—93. 复原 IP 地址

目录 题目1- 思路2- 实现⭐93. 复原 IP 地址——题解思路 3- ACM 实现 题目 原题连接&#xff1a;93. 复原 IP 地址 1- 思路 模式识别&#xff1a;给一个 String 字符串 ——> 复原 IP 地址 ——> 回溯三部曲 &#xff0c;回溯的切割问题 ——> 实现一个左闭右闭区间…

利用redis数据库管理代理库爬取cosplay网站-cnblog

爬取cos猎人 数据库管理主要分为4个模块&#xff0c;代理获取模块&#xff0c;代理储存模块&#xff0c;代理测试模块&#xff0c;爬取模块 cos猎人已经倒闭&#xff0c;所以放出爬虫源码 api.py 为爬虫评分提供接口支持 import requests import concurrent.futures import …

银河麒麟高级服务器操作系统(通用)安装和编译指定的python3版本

银河麒麟高级服务器操作系统&#xff08;通用&#xff09;安装和编译指定的python3版本 一 系统环境二 安装python3.12.42.1 安装编译需要的依赖包2.2 下载官网目前最新的python源码包2.3 解压Python-3.12.4.tar.xz2.4 配置python-3.12.42.5 编译安装2.6 配置环境变量使其生效2…

Artificial Intelligence Self-study

Artificial Intelligence Self-study Traditional AI (Symbolic AI) 基于&#xff1a;符号表示 数理逻辑 搜索 - 有明确规则&#xff0c;依靠算力。Appliance &#xff1a; 数学难题(Heuristic Algorithm)&#xff0c;棋牌对抗(围棋)&#xff0c;专家系统(输入病症&#xf…

linux安装jdk1.8(无废话版)

文章目录 1、下载安装包2、创建文件目录&#xff0c;并将安装包上传到该目录下3、解压安装包4、配置环境变量5、加载配置文件6、验证 前言&#xff1a;linux系统以ubuntu20.04.6版本为例&#xff0c;jdk版本jdk-8u411-linux-x64.tar.gz版本为例 1、下载安装包 jdk下载地址&am…

Python中列表推导式的概念以及示例

列表推导式&#xff08;List Comprehension&#xff09;是Python中一种简洁而强大的工具&#xff0c;用于从现有的可迭代对象&#xff08;如列表、元组、字符串等&#xff09;中快速生成新的列表。它提供了一种优雅的方式来表达循环和条件逻辑&#xff0c;以生成列表。列表推导…

2. 创建kvm虚拟机

创建kvm虚拟机 一、创建kvm虚拟机1、virt-manager 图形化工具2、virt-install 命令行工具3、查看虚拟机 一、创建kvm虚拟机 1、virt-manager 图形化工具 2、virt-install 命令行工具 [rootlocalhost ~]# virt-install --namevm02_centos79 \ > --graphics vnc,listen0.0.0…

linux下删除当前路径下的所有文件夹但保留文件

打开终端&#xff0c;输入&#xff0c; find . -mindepth 1 -maxdepth 1 -type d -exec rm -r {} 解释&#xff1a; find是查找文件和文件夹的命令。.表示当前路径。-mindepth 1表示最小搜索深度为1&#xff0c;这样不会包括当前目录。-maxdepth 1表示最大搜索深度为1&#x…