Feign调用开启Hystrix时无法获取ThreadLocal
2019-01-18 本文已影响0人
Hogwarts1024
在项目中使用根据请求头处理异常信息国际化的问题,但是在feign调用的时候无法传递请求头,这个问题看了好久最后才知道feign开启hystrix默认会新建一个线程,而我的请求头数据是通过拦截器放到ThreadLocal里的在新线程就无法获取了
先看一下原来是怎么实现的
首先是header封装类
@Data
public class CommonRequestHeader {
/**
* version 版本号
*/
private String version;
/**
* 平台类型
*/
private String platform;
}
把请求头封装到ThreadLocal中
@Data
public class CommonRequestHeaderHolder {
public static final ThreadLocal<CommonRequestHeader> context = new ThreadLocal<>();
public static void clear() {
context.set(null);
}
public static void setContext(CommonRequestHeader header) {
context.set(header);
}
public static CommonRequestHeader getContext() {
return context.get();
}
}
每次请求的时候通过filter封装把请求头数据放入context中
但是在feign中开启hystrix的话新线程的ThreadLocal是无法获取主线程的数据的,这个时候就要用到InheritableThreadLocal,只需要改一行代码
private static final ThreadLocal<CommonRequestData> context = new InheritableThreadLocal<>();
InheritableThreadLocal是ThreadLocal的子类,可以解决父线程和子线程的数据传输问题
当在主线程开启一个新线程时,会执行Thread的init方法
init方法中有这么一段代码
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
当父线程中的inheritableThreadLocal被赋值时,会将当前线程的inheritableThreadLocal变量进行createInheritedMap(),看一下这个方法的具体实现,它会继续调用ThreadLocalMap(parentMap),主要的目的是父线程的变量值赋值给子线程。
关于ThreadLocal可以看一下 ThreadLocal源码简单了解