【程序大侠传】异步架构应用回调数据接收接口偶发NPE

前序

在这片浩瀚的代码江湖中,各大门派林立,各自修炼独门绝技,江湖中的侠士们分别担任着开发、测试、产品和运维的角色,共同守护着这片数字化的疆域。

开发门派:代码剑宗
代码剑宗的弟子们精通各种编程语言,擅长写出优雅而高效的代码。每一个函数、每一行代码都如同剑招,精准无比,直击要害。他们不断钻研新的技术,追求极致的性能和用户体验。

  • 绝技:算法剑法
    通过优化算法,提高系统的响应速度和处理能力。
  • 绝技:架构心法
    设计出高扩展性和高可维护性的系统架构。

测试门派:断点神教
断点神教的弟子们以严谨和细致著称,他们通过各种测试手段,确保每一行代码的质量。他们的绝技如同内力,能够发现隐藏的漏洞和瑕疵,保障系统的稳定性和可靠性。

  • 绝技:白盒测试术
    通过了解代码内部结构,进行全面的测试。
  • 绝技:黑盒测试术
    从用户视角出发,进行功能和性能测试。

产品门派:需求派
需求派的弟子们擅长从用户需求出发,设计出符合市场需求的产品。他们如同江湖中的智者,洞察用户心理,预见市场趋势,为开发门派提供明确的方向。

  • 绝技:用户画像术
    分析用户行为,构建用户画像,指导产品设计。
  • 绝技:需求拆解法
    将复杂的需求拆解成可执行的任务,确保开发顺利进行。

运维门派:守护盟
守护盟的弟子们负责系统的维护和保障,如同江湖中的护法,确保系统的稳定运行。他们精通各种运维工具和技术,能够迅速应对突发问题,保障系统的高可用性。

  • 绝技:自动化部署术
    通过自动化工具,实现高效的系统部署和更新。
  • 绝技:监控预警法
    实时监控系统运行状态,及时发现并解决问题。

项目管理门派:天工阁
在这片浩瀚的代码江湖中,天工阁是一个专注于项目管理的门派。天工阁的弟子们以严谨的流程和科学的方法论著称,他们如同江湖中的策划大师,统筹全局,确保每一个项目都能顺利完成。

  • 绝技:立项心法
    准备项目背景、项目目标(含OKR目标)、项目周期、投入产出分析和产品/技术方案。
  • 绝技:目标牵引术
    通过明确项目目标,牵引运营、产品和研发各相关方达成共识。

江湖现状
在这片江湖中,各大门派互相竞争又互相协作,共同面对来自外部的挑战。开发门派、测试门派、产品门派和运维门派的弟子们通过不断修炼和切磋,提升自身的技艺,为江湖的繁荣和稳定贡献力量。

21世纪的某一天,代码剑宗的阿强正坐在洞府的蒲团上沉浸式库库思考需求派小汝提出来的一个棘手的需求落地方案而眉头紧锁,此时断点神教小美突如其来的传音“阿强,快来看看你们门派中的弟子A在参与“异步回调接口处理数据”的任务中时候偶发出现npe异常了”把阿强从精神世界中拉入现实。阿强有点无奈地摇摇了头地心里想道:“npe这种小问题,看来又是需要本座略微施展实力的时候到了”…

第一章:小问题而已

洞府外,阿强见到了阿美,阿美见到阿强就迫不及待地描述了一下受伤弟子A的内伤情况,10分钟之后,阿强已经知道基本情况,大致就是:业务系统A雇佣了弟子A去保护其安全和提供发展助力,弟子A在开发业务系统A地一次任务时偶发的发生npe异常(A系统是此次弟子所保护的系统),此任务是需要三方系统进行交互的,其中与三方系统交互是采用的异步方式。从数据层面看,A系统去请求三方系统的接口会返回一个唯一Id,A系统会根据这个唯一id记录此次的请求,此时的请求的记录状态是一个中间态,而三方处理完业务逻辑之后会通过回调A系统暴露给三方的接口去更新A系统里面的对应的那条请求记录状态至终态。大致流程图如下:
在这里插入图片描述

阿强很熟练地从兜里拿出了门派每个人都有的法器IDEA(此法器能够收录所有的系统发布的任务过程),并通过法器天书(能够记录出问题的堆栈信息)分析了整个过程,阿强最终定位到是repository获取数据为空导致:

//回调接口处理核心逻辑
public Map<String, Object> callBack(Map<String, Object> params) {
			//do something......
			//thirdId 跟 innerId 都是三方系统维护的字段
            AEntity aEntity = aRepository.selectDataByThirdIdAndInnerId(thirdId, innerId); 
           //根据堆栈,下面这行代码是异常抛出行
           String status = aEntity.getStatus();
            //do something......          
        return resultMap;
    }

而其中repository数据的录入到a系统的操作是在第一次跟三方系统进行交互的时候:

public void thirdApply(ApplyContext applyContext) {
	//do something......
	//通过http请求框架调用三方接口
	Response response = httpClient.doPost(params);
	if(response.success()){
		AEntity aEntity = new AEntity();
		//通过返回结果,组装状态参数
		aRepository.insert(aEntity);
	}
	//do something......
}

此时的阿强对于处理这个npe还是信心满满的,因为repository获取问题导致npe,无非就两种情况,要么是数据没有正常录入到数据库,要么是查询数据的条件无法在数据库中查询到数据。为了更加清晰的还原这个问题,也是为了找到偶发npe发生的根因,他通过自己的法器idea回溯当时的一次回调请求,发现并没有发生npe的异常。但是门派中记录的当时三方回调请求链路库中表示当时的一次请求发生了npe的异常。阿强此时开始在脑海里面开始头脑风暴,考虑各种造成这种现象的原因。

10分钟之后,阿强信心满满地又重新分析了一下弟子A的代码,果然,他在thirdApply这个接口中发现了一丝猫腻,系统A的记录落库是在调用三方系统之后,那考虑一种场景,如果三方系统在处理完自己逻辑并回调系统A时,A系统还没有将请求记录落库,这个时候在回调接口中会拿不到记录数据然后应用就会抛出npe的异常,与此同时,异常抛出之后,记录数完成了落库操作,三方系统再次回调就不会发生npr异常。阿强此时脑海中的画面如下:
在这里插入图片描述

第二章:小问题如何解决?

为了验证自己的想法,阿强在门派弟子A写的代码里面修改了一部分代码如下:

public void thirdApply(ApplyContext applyContext) {
	//do something......
	//通过http请求框架调用三方接口
	AEntity aEntity = new AEntity();
	//组装其他参数
	aRepository.insert(aEntity);
	Response response = httpClient.doPost(params);
	if(response.success()){
		//根据返回结果设置记录状态
		aRepository.update(aEntity);
	}
	//do something......
}

修改完之后,应用A的回调接口再没有出现过npe异常,但是随之而来的一个问题是,系统A里面的状态会出现回溯。阿强又开始了新一轮的头脑风暴,此时他的脑海中的画面如下:
在这里插入图片描述
阿强此时又开始动用他的知识库去思考解决方案,他又改了一版代码:

public void thirdApply(ApplyContext applyContext) {
	//do something......
	//通过http请求框架调用三方接口
	AEntity aEntity = new AEntity();
	//组装其他参数
	aRepository.insert(aEntity);
	Response response = httpClient.doPost(params);
	if(response.success()){
	    	LockUtil.lock(thirdId,2000){
		    	AEntity aEntityFromDb = aRepository.selectDataByThirdId(thirdId);
		    	//B是更新后的状态值
		    	if(aEntityFromDb.getStatu().equals('A')){
				    //根据返回结果设置记录状态
					aRepository.update(aEntity);
	     		}
	    	}   
	}
	//do something......
}
//回调接口处理核心逻辑
public Map<String, Object> callBack(Map<String, Object> params) {
			//do something......
			//thirdId 跟 innerId 都是三方系统维护的字段
			LockUtil.lock(thirdId,2000){
			     AEntity aEntity = aRepository.selectDataByThirdIdAndInnerId(thirdId, innerId); 
           //根据堆栈,下面这行代码是异常抛出行
              String status = aEntity.getStatus();
             //do something......  
	     	}eles{
	     	    //do error scene
	     	}         
        return resultMap;
    }

阿强改完这版之后,系统A基本上没有发生过状态问题,阿强心里也清楚,如果再出现问题,那只能是在系统负载较高的场景下了。

此时,已经过去了2个小时,阿强作为一个对可知错误无法容忍的人,他又开始了新的一轮头脑风暴,突然,阿强脑子的灵光一闪而过。他从思考角度上面重新对这个问题做了一番考量,如果让三方系统配合做一个回调的重试机制是不是就可以完美解决这个问题了呢?正当阿强想把这个新思路好好地梳理一遍的时候,天工阁小凯着急的传音随之而到,“阿强,小汝给你提的那个需求,目前的技术方案出来了吗?尽快给出这个需求的排期!!”。阿强此时对小凯的打扰非常不喜,语气不喜地录入让小凯乖乖地等他想完这个回调处理方案的传音,阿强正打算传过去时,突然想到了什么似的摇摇了头,最终取消了发送传音的想法。

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

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

相关文章

【嵌入式】探索嵌入式世界:在ARM上构建俄罗斯方块游戏的奇妙之旅

文章目录 前言&#xff1a;1. 简介2. 总体设计思路及功能描述2.1 设计思路2.2 功能描述2.3 程序流程图 3. 各部分程序功能及详细说明3.1 游戏界面函数3.1.1 游戏界面中的图片显示3.1.2 游戏开始界面3.1.3 游戏主界面3.1.4 游戏结束广告界面3.1.5 游戏界面中的触摸反馈3.1.6 游戏…

【Spring Boot】基于 JPA 开发的文章管理系统(CRUD)

基于 JPA 开发的文章管理系统&#xff08;CRUD&#xff09; 1.实现文章实体2.实现数据持久层3.实现服务接口和服务接口的实现类3.1 创建服务接口3.2 编写服务接口的实现 4.实现增、删、改、查的控制层 API 功能4.1 获取文章列表4.2 根据 id 获取文章对象4.3 新增4.4 保存4.5 删…

第三届环境工程与可持续能源国际会议(EESE 2024)

随着全球气候变化和环境问题日益严峻&#xff0c;环境工程与可持续能源领域的研究和发展显得尤为重要。第三届环境工程与可持续能源国际会议&#xff08;EESE 2024&#xff09;作为这一领域的重要交流平台&#xff0c;将于2024年10月25日至27日在湖南长沙盛大召开。本次会议将汇…

算法实验2.2、2.3

2.2主要内容 比较快速排序&#xff0c;归并排序以及堆排序算法的时间效率。了解影响算法执行时间的 主要因素以及如何降低算法的执行时间。 #include<iostream> using namespace std; #include<stdio.h> #include<malloc.h> #include<stdlib.h> #inc…

vue全局方法plugins/utils

一、在src目录下创建一个plugins文件夹 test.ts文件存放创建的方法&#xff0c;index.ts用于接收所有自定义方法进行统一处理 二、编写自定义方法 // test.ts文件 export default {handleTest(val1: number, val2: number) {// 只是一个求和的方法return val1 val2;}, };三…

MySQL数据库的主从复制与读写分离

一、MySQL数据库的主从复制 1.主从复制的概述及原理 &#xff08;1&#xff09;主从复制的意义 在实际的生产环境中&#xff0c;如果对数据库的读和写都在同一个数据库服务器中操作,无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此&#xff…

【Nvidia+AI相机】涂布视觉检测方案专注提高锂电池质量把控标准

锂电池单元的质量在多个生产制造领域都至关重要&#xff0c;特别是在新能源汽车、高端消费电子等行业。这些领域的产品高度依赖锂电池提供持续、稳定的能量供应。优质的锂电池单元不仅能提升产品的性能和用户体验&#xff0c;还能确保使用安全。因此&#xff0c;保证锂电池单元…

微信小程序template模板引入

如图&#xff1a;temp.wxml是template引入的模板 在two.wxml中&#xff1a; import&#xff1a;是引入temp的页面让template中的内容显示出来在two页面中&#xff1b; include:是显示temp页面内容不在template包裹&#xff0c;template以外的view标签文字和不在view的文字让…

探索PcapPlusPlus开源库:网络数据包处理与性能优化

文章目录 0. 本文概要1. PcapPlusPlus介绍1.1 概述1.2主要特性和功能1.3 PcapPlusPlus 主要模块关系和依赖1.4 网络协议层处理过程 2. 实例2.1 基于 PcapPlusPlus 的应用程序设计和封装流程&#xff1a;2.2 多线程示例代码2.3 代码说明&#xff1a; 3. 程序性能进一步优化3.1 避…

Golang内存分配

Go内存分配语雀笔记整理 Golang内存模型设计理念思考核心代码阅读mspanmcachemcentral中心缓存mheap分配过程 Golang内存模型设计理念思考 golang内存分配基于TCmalloc模型&#xff0c;它核心在于&#xff1a;空间换时间&#xff0c;一次缓存&#xff0c;多次复用&#xff1b;…

基于x86+FPGA+AI轴承缺陷视觉检测系统,摇枕弹簧智能检测系统

一、承缺陷视觉检测系统 应用场景 轴类零件自动检测设备&#xff0c;集光、机、软件、硬件&#xff0c;智能图像处理等先进技术于一体&#xff0c;利用轮廓特征匹配&#xff0c;目标与定位&#xff0c;区域选取&#xff0c;边缘提取&#xff0c;模糊运算等算法实现人工智能高…

Linux 高级编程——线程控制

线程控制&#xff1a;互斥与同步 概念&#xff1a; 互斥 》在多线程中对临界资源的排他性访问。 互斥机制 》互斥锁 》保证临界资源的 访问控制。 pthread_mutex_t mutex; 互斥锁类型 互斥锁变量 内核对象 框架&#xff1a; 定义互斥锁 》初始化锁 》加…

Kafka-服务端-副本同步-源码流程

杂 在0.9.0.0之前&#xff0c;Kafka提供了replica lag.max.messages 来控制follower副本最多落后leader副本的消息数量&#xff0c;follower 相对于leader 落后当超过这个数量的时候就判定该follower是失效的&#xff0c;就会踢出ISR&#xff0c;这里的指的是具体的LEO值。 对…

Hadoop权威指南-读书笔记-01-初识Hadoop

Hadoop权威指南-读书笔记 记录一下读这本书的时候觉得有意思或者重要的点~ 第一章—初识Hadoop Tips&#xff1a; 这个引例很有哲理嘻嘻&#x1f604;&#xff0c;道出了分布式的灵魂。 1.1 数据&#xff01;数据&#xff01; 这一小节主要介绍了进入大数据时代&#xff0c;面…

【windows|012】光猫、路由器、交换机详解

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…

QML学习——Qt Quick Extras Examples 1.4(八)

Qt Quick Extras Examples 阅读官方的源码然后尝试做了下 01 A car dashboard 样例演示&#xff1a; 说明&#xff1a; ValueSource组件控制数值相关的动画&#xff0c;例如图中数值的变化&#xff1b;TurnIndicator组件是控制左右方向灯的闪烁和背景&#xff0c;里面使用…

excel修改批量一列单价的金额并保留1位小数

1.打开表格&#xff0c;要把单价金额变成现在的两倍&#xff0c;数据如下&#xff1a; 2.把单价这一列粘贴到一个新的sheet页面&#xff0c;在B2单元格输入公式&#xff1a;A2*2 然后按enter回车键,这时候吧鼠标放到B2单元格右下角&#xff0c;会出现一个黑色的小加号&#xf…

SQL 注入联合查询之为什么要 and 1=2

在 SQL 注入联合查询中&#xff0c;将 id 先置为假&#xff08;如 id-1 或其他使查询结果为空的条件&#xff09;&#xff0c;通常是为了让前面的查询语句查询不到结果&#xff0c;从而使联合查询中后面的语句结果能够显示在回显位上

【深度学习】pytorch训练中的一个大坑

使用的命令&#xff1a;iostat -x 5 可以看到 ssd的利用率已经满了。 之前在的数据集放在了 hdd上&#xff0c;训练结果特别慢。 所以我把它移动到了ssd上&#xff0c;然后训练参数用的 resume&#xff0c; 但是&#xff01;&#xff01;&#xff01;&#xff01;它把历史记住…