1、Feign远程调用丢失请求头问题

​ 在订单服务向购物车服务发起远程调用时,在购物车服务中获取不到用户信息,原因是用户的信息是基于SpringSession保存在redis中,key存在于浏览器的cookie中,当在浏览器中发起请求时,由于请求会默认带上cookie,所以可以正常获取到数据信息,但在这个业务中是由Feign发起的远程调用走到购物车服务,Feign远程调用时会创建一个新的request,里面没有cookie数据,所以在购物车服务中获取不到用户数据。

​ 解决办法,由于Feign在远程调用之前都会调用很多拦截器(默认没有拦截器),可以写一个Feign的请求拦截器扩展Feign的功能,在新的request中加入cookie

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuration
public class FeignConfig {

@Bean
public RequestInterceptor requestInterceptor(){
return new RequestInterceptor(){
@Override
public void apply(RequestTemplate template) {
//通过上下文环境保持器拿到当前请求的所有属性RequestAttributes ->
// RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//同步请求头数据
template.header("Cookie", request.getHeader("Cookie"));
}
};
}
}

2、Feign异步情况丢失上下文问题

​ 在上一个问题中,对于Feign的远程调用请求头丢失问题,引入了RequestInterceptor来解决,但这种办法只能针对同步问题,当使用异步编排发起Feign远程调用时,ServletRequestAttributes中就回去不到原来线程的request数据,就会报空指针异常。

image-20230108205538489

​ 如上图所示,RequestContextHolder是利用ThreadLocal共享数据,所以会发生这种问题。

​ 解决办法是在异步编排之前,先获取主线程的上下文,在进入新线程后再把主线程的上下文放到新线程里面。