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源码简单了解

上一篇下一篇

猜你喜欢

热点阅读