记一次SpringCloud OpenFeign 服务调用传递 token @Async 上下文信息获取失败

一、场景

在异步方法中使用了feign调用,发现提示“您还未登录或登录已失效”。那原因很明了就是我的登录信息没办法传入到feign的调用方法里。
在这里插入图片描述

二、考虑的解决办法

1)尝试一:ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
sendAsyncService.statisticsSendSms(idList, userTokenValue, sendSMSNotificationParams, coreDescriptionParams, attributes);
public void statisticsSendSms(List<Long> reportIdList,UserTokenValue userTokenValue,SendSMSNotificationParams sendSMSNotificationParams,CoreDescriptionParams coreDescriptionParams,ServletRequestAttributes attributes) {// 设置子线程共享RequestContextHolder.setRequestAttributes(attributes, true);//figen 调用,需要tokenResponseResult<String> responseResult = smsApi.sendSMSNotification(sendSMSNotificationParams);

这种情况犹豫反复在测试环境测试,都无任何问题,心里自信满满,但是上线后,却暴漏了,依旧提示“您还未登录或登录已失效”。这是什么情况?

1-1)RequestContextHolder跨线程获取不到requests请求对象的原因

为何会失败呢?因为异步注解,顾名思义,是开启了一个新的线程去执行一些代码。
在这里插入图片描述
在这里插入图片描述

/*** 给当前线程绑定属性* @param inheritable 是否要将属性暴露给子线程* */
public static void setRequestAttributes(@Nullable RequestAttributes attributes, boolean inheritable) {if (attributes == null) {resetRequestAttributes();}else {if (inheritable) {inheritableRequestAttributesHolder.set(attributes);requestAttributesHolder.remove();}else {requestAttributesHolder.set(attributes);inheritableRequestAttributesHolder.remove();}}}

那源代码理解,已经将属性暴漏给子线程了,为何上线后依旧是获取不到呢?那其实从根本思考,主线程加入相应速度快于子线程呢,结果会是如何?结果就是主线程结束,所有的信息都已经销毁了,谁还管你子线程是否执行没执行呢,哈哈哈。测试环境未复现,是因为环境配置低,可能测试的几次都一定概率的主线程相应时间大于了子线程的相应时间,到了线上,由于高配置的环境,这种平衡性被打破了,主线程先行一步了。
缘由了解了,解决的办法也就来了----肯定就是让主线程等一下,等子线程执行完再结束,可是主线程会那么礼貌吗?该如何解决这个问题呢?

2)自定义异步线程池,配置中做相关处理

// 解决使用@Async注解,获取不到上下文信息的问题executor.setTaskDecorator(runnable -> {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();AsyncContext asyncContext;if (attributes!=null){HttpServletRequest request=attributes.getRequest();asyncContext=request.startAsync();} else {asyncContext = null;}return ()->{try {// 我们set 进去 ,其实是一个ThreadLocal维护的.RequestContextHolder.setRequestAttributes(attributes);runnable.run();}finally {RequestContextHolder.resetRequestAttributes();if (asyncContext!=null){asyncContext.complete();}}};});

2-1)Servlet的异步处理

是由AsyncContext接口来实现的。

AsyncContext asyncContext;if (attributes!=null){HttpServletRequest request=attributes.getRequest();asyncContext=request.startAsync();} else {asyncContext = null;}

2-3)异步注解使用了自定义线程池,避免一个方法多个异步注解使用

@Async("asyncServiceExecutor")
AsyncContext asyncContext;if (attributes!=null){HttpServletRequest request=attributes.getRequest();asyncContext=request.startAsync();} else {asyncContext = null;}

由于线程池中我们使用了Servlet的异步处理来 set我们需要的token信息,所以避免重复调用。多次调用会报错,即使不影响信息获取。
在Servlet中多次调用自定义线程池可能导致错误,这通常是因为Servlet的单实例模式导致的线程安全问题。Servlet容器通常会为每个Servlet维护一个实例,当多个请求同时访问同一个Servlet实例时,可能会出现竞态条件,比如多个线程尝试使用相同的资源或状态。

三、错误使用记录

1)java.lang.IllegalStateException: Calling [asyncStart()] is not valid for a request with Async state [STARTING]

在这里插入图片描述

1-1)报错解析:

表明你正在尝试对一个已经被dispatch()方法分派的异步请求执行asyncStart()操作,而这不被允许。
在Java的Servlet API中,异步处理允许请求处理过程中转移到其他线程继续执行,而不阻塞原始请求线程。当你调用request.startAsync()或request.getAsyncContext()时,会创建一个AsyncContext对象。在这个对象被分派之后,原始请求线程可能已经结束,而新的线程继续处理异步的任务。
解决这个问题的方法是确保在调用asyncStart()之前不要对AsyncContext进行分派操作。如果你需要在异步处理中启动新的线程,应该在调用request.startAsync()之后立即进行,并确保不会有进一步的分派发生。

2)解决办法:整个方法内只能允许一个异步调用,配置代码如上。

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

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

相关文章

【C语言进阶】文件操作:文件的打开与文件的读写以及文本文件和二进制文件

目录 1、为什么使用文件 2、什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3、文件的打开和关闭 3.1文件指针 3.2文件的打开与关闭 4、文件的顺序读写 4.1 几个函数的区别 5、文件随机读写 5.1 fseek 5.2 ftell 5.3 rewind 6、文本文件和二进制文件…

springboot+vue+mybatis超市管理-简单版+PPT+论文+讲解+售后

使用旧方法对超市信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在超市信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的小型超市管理系统有管理员&…

探索DIYGW可视化开发工具:提升UniApp项目效率与质量的新途径

一、引言 在快速迭代和不断创新的移动应用开发领域中&#xff0c;开发者们常常面临着一个共同的挑战&#xff1a;如何在保证开发质量的同时&#xff0c;缩短开发周期。近期&#xff0c;一款名为DIYGW的可视化开发工具进入了我们的视野&#xff0c;它以其独特的拖拽式开发方式和…

算法题-给定一个日期,输出星期几

目录 给定日期&#xff0c;输出对应是星期几 测试结果 如1900年 5月6日是星期三&#xff0c;计算给的日期是星期几 给定日期&#xff0c;输出对应是星期几 #include <stdio.h> #include <stdlib.h> #include <string.h>int main() {char input[100];int d…

如何被谷歌收录?

最简单的方法就是提交网站给谷歌&#xff0c;但这种方法可操作空间不大&#xff0c;一天一般也就只有十条左右的链接可以提交&#xff0c;对于一些大网站来说&#xff0c;这种方法显然不适用&#xff0c;这时候GPC爬虫池的好处就体现了&#xff0c;GPC爬虫池对希望提升Google搜…

Deepin Linux 深度 V23 beige 官方源及换镜像源方法。

Deepin Linux 深度 V23 英文版本号&#xff1a;beige 谁起的烂名字。。。。。。 1. 打开文件管理器&#xff0c;在apt文件夹点右键&#xff08;以管理员身份打开&#xff09;&#xff0c; 2. 输入你的登录密码&#xff0c;以便打开文件夹&#xff08;管理员权限&#xff09;。…

【MySQL数据库】索引与事务

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【MySQL】探秘&#xff1a;数据库世界的瑞士军刀 目录 &#x1f5f3;️一.索引 &#x1f4ee;1.工作原理 &#x1f4ec;2.类型 &#x1f4ed;3.作用 &#x1f4ea;4.优缺点 &#x1f4eb;5.使用…

【Modelground】个人AI产品MVP迭代平台(2)——网站从0-1部署教程

文章目录 1.选购一台云服务器2. 购买域名3. 通过nginx部署静态网站4. 通过gitee在云服务器拉取代码5. ICP备案总结 1.选购一台云服务器 目前阿里云在促销&#xff0c;一台2核2GB内存3Mbps宽带的云服务器&#xff0c;一年只需要99元&#xff0c;学生更便宜&#xff0c;我认为这…

Java——处理键盘输入

在Java中&#xff0c;可以使用多种方式来处理键盘输入。最常用的一种方法是使用 Scanner 类&#xff0c;它位于 java.util 包中。 一、使用 Scanner 类处理键盘输入 1、具体操作步骤 1&#xff09;导入 Scanner 类 在开始编写代码之前&#xff0c;需要导入 java.util.Scann…

【TB作品】MSP430F5529,单片机,电子秒表,秒表

硬件 MSP430F5529开发板7针0.96寸OLED /* OLED引脚分配 绿色板子DO(SCLK)------P4.3D1(DATA)------P4.0RES-----------P3.7DC------------P8.2CS------------P8.1 */ 程序功能 该程序是一个用C语言编写的&#xff0c;用于msp430f5529微控制器上的简单电子秒表应用。它使用…

1882java密室逃脱管理系统 Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java密室逃脱管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助采用了java设计&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用web模式&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&…

7.2 Go 使用error类型

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

数论1---整除

概念与基本性质就不说了 例题1&#xff1a;已知a|n&#xff0c;b|n.且axby1,求证&#xff1a;ab|n 即&#xff1a; 所以&#xff1a;ab|n 例题2&#xff1a;设m是一个大于2的正整数&#xff0c;证明&#xff1a;对于任意正整数n&#xff0c;都有 由于我不想打公式了直接拍照…

react-native 默认停用 flipper 通知

react-native 0.74 默认停用 flipper &#xff0c;但仍然可以手动安装 flipper 官方声明文档 英语好的可以直接阅读。 integration with React Native will no longer be enabled 原因 增加编译时间有时候会有连接问题升级会导致不能使用 之后调试推荐 我们建议团队使用 A…

【Qt知识】Qt窗口坐标系

Qt的窗口坐标体系遵循标准的计算机图形坐标系统规则 Qt窗口坐标体系特点 坐标原点&#xff1a;窗口坐标体系的原点位于窗口的左上角&#xff0c;即坐标(0, 0)位置。 轴方向&#xff1a; X轴&#xff1a;向右为正方向&#xff0c;随着X坐标值的增加&#xff0c;元素在窗口中从…

opencv-python(二)

马赛克 img cv2.imread(./bao.jpeg)print(img.shape)img2 cv2.resize(img,(35,23))img3 cv2.resize(img2,(900,666))cv2.imshow(bao,img3)cv2.waitKey(0)cv2.destroyAllWindows()img2 cv2.resize(img, (90,66))img3 np.repeat(img2, 10, axis 0) # 重复行img4 np.repeat(…

数据结构---时间复杂度与空间复杂度

文章目录 1. 知识背景2. 什么是时间复杂度&#xff1f;3. 空间复杂度4 .大O渐进表示法&#xff1a;对于一些算法的时间复杂度存在最好&#xff0c;最坏&#xff0c;平均的情况&#xff1a; 5. 常见的时间复杂度举例总结&#xff1a;6. 空间复杂度的举例与总结&#xff1a;总结&…

腾讯 InstantMesh,单图生成 3D 模型,10 秒内完成,性能超越 SOTA

前言 近年来&#xff0c;3D 内容创作在游戏、动画、虚拟现实等领域发挥着越来越重要的作用。然而&#xff0c;传统的 3D 模型制作流程繁琐&#xff0c;需要专业人员花费大量时间和精力。为了简化 3D 内容创作流程&#xff0c;腾讯 ARC 实验室推出了 InstantMesh&#xff0c;一…

开源代码分享(32)-基于改进多目标灰狼算法的冷热电联供型微电网运行优化

参考文献&#xff1a; [1]戚艳,尚学军,聂靖宇,等.基于改进多目标灰狼算法的冷热电联供型微电网运行优化[J].电测与仪表,2022,59(06):12-1952.DOI:10.19753/j.issn1001-1390.2022.06.002. 1.问题背景 针对冷热电联供型微电网运行调度的优化问题&#xff0c;为实现节能减排的目…

prometheus-alert使用

说明&#xff1a;本文介绍一款可接管alertmanager报警&#xff0c;简化alertmanager配置的组件prometheus-alert。可以将prometheus检测到的异常指标&#xff0c;通过alertmanager转给prometheus-alert&#xff0c;由prometheus-alert通知到各个应用。 如下&#xff1a; 上图来…