记一次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 调用,需要token
		ResponseResult<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实例时,可能会出现竞态条件,比如多个线程尝试使用相同的资源或状态。

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

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

相关文章

高维数组到向量的转换:两种方法的深度解析

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;高维数组的挑战与需求 二、方法一&#xff1a;使用NumPy库进行展平 示…

【数据分析面试】56.数据格式转换(Python:melt函数)

题目 给定一个df&#xff0c;包含ABCDE多个列。请编写一个 Python 程序&#xff0c;将列 ‘D’ 和 ‘E’ 转换为长格式&#xff0c;并使用 ‘A’、‘B’ 和 ‘C’ 作为标识符。 换句话说&#xff0c;将数据中的D、E两列转换为行&#xff0c;使数据从宽变长。 示例&#xff1…

BH-0.66 6000/5/150电流互感器 塑壳 JOSEF约瑟

BH-0.66 15/5塑壳式电流互感器 BH-0.66 20/5塑壳式电流互感器 BH-0.66 30/5塑壳式电流互感器 BH-0.66 40/5塑壳式电流互感器 BH-0.66 50/5塑壳式电流互感器 BH-0.66 75/5塑壳式电流互感器 BH-0.66 100/5塑壳式电流互感器 BH-0.66 150/5塑壳式电流互感器 BH-0.66 200/5塑壳式…

职校老师的工资待遇怎么样

工资水平一直是教师们关注的焦点&#xff0c;毕竟&#xff0c;工资不仅关系到个人的生活品质&#xff0c;还影响着教师的职业满意度和工作动力。职校教师的工资待遇究竟是怎样的呢&#xff1f; 职校教师的工资水平受多种因素影响&#xff0c;包括地区、学校类型、个人资历和教学…

【OrangePi AIpro】香橙派 AIpro 为AI而生

产品简介 OrangePi AIpro(8T)&#xff1a;定义边缘智能新纪元的全能开发板 在当今人工智能与物联网技术融合发展的浪潮中&#xff0c;OrangePi AIpro(8T)凭借其强大的硬件配置与全面的接口设计&#xff0c;正逐步成为开发者手中的创新利器。这款开发板不仅代表了香橙派与华为…

pyqt Qtreeview分层控件

pyqt Qtreeview分层控件 介绍效果代码 介绍 QTreeView 是 PyQt中的一个控件&#xff0c;它用于展示分层数据&#xff0c;如目录结构、文件系统等。QTreeView 通常与模型&#xff08;如 QStandardItemModel、QFileSystemModel 或自定义模型&#xff09;一起使用&#xff0c;以管…

【机器学习300问】105、计算机视觉(CV)领域有哪些子任务?

计算机视觉作为人工智能的重要分支&#xff0c;发展至今已经在诸多领域取得显著的成果。在众多的计算机视觉任务中&#xff0c;图像分类、目标检测与定位、语义分割和实例分割是四个基本而关键的子任务&#xff0c;它们在不同的应用场景下扮演着重要角色。这四个子任务虽然各具…

【408真题】2009-23

“接”是针对题目进行必要的分析&#xff0c;比较简略&#xff1b; “化”是对题目中所涉及到的知识点进行详细解释&#xff1b; “发”是对此题型的解题套路总结&#xff0c;并结合历年真题或者典型例题进行运用。 涉及到的知识全部来源于王道各科教材&#xff08;2025版&…

Ps系统教程03

选区工具的组合使用 先用魔棒将大致区域点击圈主 会发现一些零散的小区域 使用套索工具进行区域的加减&#xff08;按住shift/alt键进行相关区域加减&#xff09; 可以放大查看 基本处理完细节之后 如果把不用的填充背景直接按delete删除&#xff0c;那么原版图案就会…

研学活动报名二维码怎么制作?

在组织研学活动时&#xff0c;老师们经常面临报名流程繁琐、信息收集不全面、统计工作耗时等问题&#xff1f;如何高效地管理学生的报名信息&#xff0c;确保活动顺利进行呢&#xff1f; 现在我们有了更多的选择。老师们可以快速制作出研学活动的研学活动报名二维码怎么制作&am…

深度解析搜索引擎广告(SEM)与社交媒体广告(SMM):NetFarmer助力企业数字化出海

在当今数字化时代&#xff0c;企业出海已经成为了一个必然趋势。然而&#xff0c;如何有效地在海外市场中推广品牌、吸引潜在客户&#xff0c;成为了众多企业面临的重要挑战。搜索引擎广告&#xff08;SEM&#xff09;和社交媒体广告&#xff08;SMM&#xff09;作为两种主要的…

Ex 防爆标准解读

以如下标准为例&#xff1a; Ex t IIIB T2 40 Db 解读&#xff1a; Ex防爆 t&#xff1a; IIIB T2 40 T2为温度等级&#xff0c;40为最大表面温度40度 Db 设备防护用于22区 类似铭牌为

能芯(EnChip)模拟芯片应用和选型

数据显示&#xff0c;超过60%的驾驶者会在开车时听音乐&#xff0c;这不仅可以提高驾驶者的注意力&#xff0c;还可以缓解驾驶过程中产生的疲劳和压力&#xff0c;特别是在长途驾驶或交通拥堵时尤其明显。基于音乐欣赏&#xff0c;高保真音质是音响系统的核心指标之一&#xff…

【考研数学】李艳芳900比李林880难吗?值得做吗?

差不多&#xff0c;只能说基础没搞好刷这两个都很费劲 李艳芳900题把每个章节题目划分为ABC三个难度级别&#xff0c;题目选取的难度较大也比较新颖&#xff0c;计算量也非常接近考研趋势&#xff0c;原创性很高&#xff0c;比较适合过完一轮的同学继续做补充和强化 880算是比…

算法与数据结构:二叉排序树与AVL树

ACM大牛带你玩转算法与数据结构-课程资料 本笔记属于船说系列课程之一&#xff0c;课程链接&#xff1a; 哔哩哔哩_bilibilihttps://www.bilibili.com/cheese/play/ep66799?csourceprivate_space_class_null&spm_id_from333.999.0.0 你也可以选择购买『船说系列课程-年度会…

【C++】:vector容器的底层模拟实现迭代器失效隐藏的浅拷贝

目录 &#x1f4a1;前言一&#xff0c;构造函数1 . 强制编译器生成默认构造2 . 拷贝构造3. 用迭代器区间初始化4. 用n个val值构造5. initializer_list 的构造 二&#xff0c;析构函数三&#xff0c;关于迭代器四&#xff0c;有关数据个数与容量五&#xff0c;交换函数swap六&am…

R语言入门 | 使用 ggplot2 进行数据可视化

1.0准备工作 先下好tidyverse包&#xff0c;并进行加载。 install.packages ( "tidyverse" ) library(tidyverse) R 包只需安装一次&#xff0c;但每次开始新会话时都要重新加载。 1.1 数据框 数据框是变量&#xff08;列&#xff09;和观测&#xff08;行&#x…

AppInventor2 表格布局的外面的黑框怎么去掉?

问&#xff1a;表格布局的外面的黑框怎么去掉啊&#xff1f; 答&#xff1a;这个黑框是界面设计的布局位置示意&#xff0c;实际 App 测试时并没有框。 来源&#xff1a;AppInventor2 表格布局的外面的黑框怎么去掉&#xff1f; - App应用开发 - 清泛IT社区&#xff0c;为创新…

【错题集-编程题】天使果冻(递推)

牛客对应题目链接&#xff1a;天使果冻 (nowcoder.com) 一、分析题目 预处理 递推 / 动态规划 f[i]&#xff1a;表示前 i 个数中的最大值。g[i]&#xff1a;表示前 i 个数中的第二大的值。 状态转移方程&#xff1a; f[i] max(f[i-1], arr[i]);arr[i] > f[i-1]&#xf…

数据结构(十)图

文章目录 图的简介图的定义图的结构图的分类无向图有向图带权图&#xff08;Wighted Graph&#xff09; 图的存储邻接矩阵&#xff08;Adjacency Matrix&#xff09;邻接表代码实现 图的遍历深度优先搜索&#xff08;DFS&#xff0c;Depth Fisrt Search&#xff09;遍历抖索过程…