后端接收http请求时,通过线程池异步处理:在子线程中发起feign接口请求,出现如下异常
Exception in thread "pool-2-thread-1" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
尝试添加让子线程共享主线程上下文的代码后,出现如下异常:
// 子线程继承主线程的上下文
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
RequestContextHolder.setRequestAttributes(requestAttributes, true);
Exception in thread "pool-2-thread-1" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: Cannot ask for request attribute - request is not active anymore!
Caused by: java.lang.IllegalStateException: Cannot ask for request attribute - request is not active anymore!
1、错误信息:上面抛错的信息,是在说http的request作用域就是在一次性的会话线程上,当回话结束的时候,会话线程也在不可用的状态,也就拿不到request上的属性信息了。主要你异步处理的时候,http的请求线程已经结束了导致的这个错误
2、你的想法是后端接收http请求时,通过线程池异步处理:在子线程中发起feign接口请求。我的一个想法是可用绕过线程变量同步的,后端接收http请求后把请求的数据都放到一个队列,线程池异步的消费这队列,再去在子线程中发起feign接口请求。希望这个想法对你有用。
本来通过线程池去获取调用线程的普通变量副本就有风险了,没搞好很容易出问题;
还在线程池里面去获取request信息,更会出问题,都异步了,前面的注线程很容易就先执行完,request就销毁了;
简单点在主线程里面把变量取出来,当做参数传递;
解决方案:在线程调用方法时当参数传递,之前线上有遇到这个问题,传递时也不能间接的获取,必须要直接给具体的值或者对象
3楼正解。多说一句,个人建议,多线程好好补下课。不管是子线程还是主线程还是孙子线程,都分别是不同的线程
查看FrameworkServlet
源码如下:
默认是不允许类似RequestContextHolder这种上下文对象父子继承的, 如果想用可以自己更改对应设置:
但是需要注意官方的警告:
传参
定义公共变量,通过线程互斥的方式访问变量。
只能通过传参的方式,在线程调用方法的时候当参数传递
这个使用全局的变量试试
设置全局变量,传递参数即可