谷粒商城实战笔记-问题记录-Feign异步调用丢失请求头问题

本文主要是介绍谷粒商城实战笔记-问题记录-Feign异步调用丢失请求头问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 单线程下生效的原理
  • 多线程下Interceptor不生效的原因
  • 解决方案
    • 1,不优雅的方法
    • 2,优雅的方法

在请求多个信息时,我们使用了多线程,这就带来了一个问题,前面我们解决Feign丢失请求头的方案在多线程下,不再有效,丢失请求头的问题再度出现。

在这里插入图片描述

单线程下生效的原理

  1. 请求处理流程
    在单线程环境下,请求的处理流程是顺序的。当一个请求到达时,它会被控制器(Controller)处理。控制器会调用服务(Service)来处理业务逻辑。在这个过程中,请求相关的数据会被存储在ThreadLocal中。

  2. RequestContextHolder
    RequestContextHolder是一个工具类,它提供了获取当前请求相关数据的方法。在单线程环境下,当一个请求被处理时,RequestContextHolder.getRequestAttributes()会返回当前请求的ServletRequestAttributes。这个ServletRequestAttributes包含了请求相关的数据,包括请求头。

  3. RequestInterceptor
    当Feign客户端发送请求时,RequestInterceptorapply方法会被调用。在这个方法中,通过RequestContextHolder.getRequestAttributes()获取当前请求的ServletRequestAttributes,然后将请求头添加到新的请求中。由于在单线程环境下,请求的处理是顺序的,因此RequestInterceptor能够正确地获取到请求头,并将其添加到新的请求中。

多线程下Interceptor不生效的原因

  1. 多线程环境
    在多线程环境下,每个线程都有自己的请求上下文。当一个线程处理请求时,它会将请求相关的数据存储在ThreadLocal中。然而,当这个线程处理完请求后,它会释放这些数据,以便其他线程可以使用ThreadLocal来存储自己的请求数据。

  2. RequestContextHolder
    在多线程环境下,当一个线程处理完请求后,它会释放ThreadLocal中的请求数据。这意味着,当另一个线程处理请求时,它不会访问到前一个线程的请求数据,包括请求头。因此,即使使用了RequestInterceptor,多线程下还是会丢失header头。

  3. Controller和Service是否在同一线程
    在多线程环境下,控制器(Controller)和服务(Service)可能不在同一个线程中。当控制器处理请求时,它会将请求相关的数据存储在ThreadLocal中。然而,当控制器调用服务来处理业务逻辑时,这个请求数据可能会被释放,以便其他线程可以使用ThreadLocal来存储自己的请求数据。因此,即使服务在同一个线程中,它也可能无法访问到控制器的请求数据,包括请求头。

通过以上分析,单线程下生效的原理在于请求的处理是顺序的,RequestInterceptor能够正确地获取到请求头,并将其添加到新的请求中。而多线程下Interceptor不生效的原因在于ThreadLocal的作用域和多线程环境,以及控制器和服务可能不在同一个线程中。

解决方案

1,不优雅的方法

在创建线程的之前把ThreadLocal中内容取出,然后设置到子线程的ThreadLocal中。

在这里插入图片描述
但这样做会侵入业务代码,且每使用一个线程就要写这样一段代码,还会导致大量冗余代码。

2,优雅的方法

创建一个抽象类,实现Runnable方法。

public abstract class MyRunnable implements Runnable{private RequestAttributes requestAttributes;public MyRunnable() {requestAttributes = RequestContextHolder.getRequestAttributes();}public abstract void myRun();@Overridepublic void run() {//每一个线程都来共享之前的请求数据RequestContextHolder.setRequestAttributes(requestAttributes);myRun();}
}

用法如下:
在这里插入图片描述
使用第二种方法,巧妙地把设置对象的工作放在了创建线程对象的构造过程中。

//开启第一个异步任务CompletableFuture<Void> addressFuture2 = CompletableFuture.runAsync(new MyRunnable() {@Overridepublic void myRun() {//1、远程查询所有的收获地址列表List<MemberAddressVo> address = memberFeignService.getAddress(memberResponseVo.getId());confirmVo.setMemberAddressVos(address);}}, threadPoolExecutor);

这篇关于谷粒商城实战笔记-问题记录-Feign异步调用丢失请求头问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复

VS配置好Qt环境之后但无法打开ui界面的问题解决

《VS配置好Qt环境之后但无法打开ui界面的问题解决》本文主要介绍了VS配置好Qt环境之后但无法打开ui界面的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目UKeLvb录找到Qt安装目录中designer.UKeLvBexe的路径找到vs中的解决方案资源

Java Spring 中的监听器Listener详解与实战教程

《JavaSpring中的监听器Listener详解与实战教程》Spring提供了多种监听器机制,可以用于监听应用生命周期、会话生命周期和请求处理过程中的事件,:本文主要介绍JavaSprin... 目录一、监听器的作用1.1 应用生命周期管理1.2 会话管理1.3 请求处理监控二、创建监听器2.1 Ser

C/C++和OpenCV实现调用摄像头

《C/C++和OpenCV实现调用摄像头》本文主要介绍了C/C++和OpenCV实现调用摄像头,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录准备工作1. 打开摄像头2. 读取视频帧3. 显示视频帧4. 释放资源5. 获取和设置摄像头属性

Apache 高级配置实战之从连接保持到日志分析的完整指南

《Apache高级配置实战之从连接保持到日志分析的完整指南》本文带你从连接保持优化开始,一路走到访问控制和日志管理,最后用AWStats来分析网站数据,对Apache配置日志分析相关知识感兴趣的朋友... 目录Apache 高级配置实战:从连接保持到日志分析的完整指南前言 一、Apache 连接保持 - 性

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

apache的commons-pool2原理与使用实践记录

《apache的commons-pool2原理与使用实践记录》ApacheCommonsPool2是一个高效的对象池化框架,通过复用昂贵资源(如数据库连接、线程、网络连接)优化系统性能,这篇文章主... 目录一、核心原理与组件二、使用步骤详解(以数据库连接池为例)三、高级配置与优化四、典型应用场景五、注意事

Java使用MethodHandle来替代反射,提高性能问题

《Java使用MethodHandle来替代反射,提高性能问题》:本文主要介绍Java使用MethodHandle来替代反射,提高性能问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录一、认识MethodHandle1、简介2、使用方式3、与反射的区别二、示例1、基本使用2、(重要)

python web 开发之Flask中间件与请求处理钩子的最佳实践

《pythonweb开发之Flask中间件与请求处理钩子的最佳实践》Flask作为轻量级Web框架,提供了灵活的请求处理机制,中间件和请求钩子允许开发者在请求处理的不同阶段插入自定义逻辑,实现诸如... 目录Flask中间件与请求处理钩子完全指南1. 引言2. 请求处理生命周期概述3. 请求钩子详解3.1

SpringBoot实现文件记录日志及日志文件自动归档和压缩

《SpringBoot实现文件记录日志及日志文件自动归档和压缩》Logback是Java日志框架,通过Logger收集日志并经Appender输出至控制台、文件等,SpringBoot配置logbac... 目录1、什么是Logback2、SpringBoot实现文件记录日志,日志文件自动归档和压缩2.1、