Feign调用开启Hystrix时无法获取ThreadLocal

在项目中使用根据请求头处理异常信息国际化的问题,但是在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源码简单了解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,430评论 11 349
  • Ribbon配置 全局配置 由于Spring cloud Feign的客户端负载均衡是通过spring cloud...
    二月_春风阅读 11,519评论 0 13
  • 一、推荐阅读 可能有部分同学对 Hystrix 的特性了解的不是很清晰,推荐如下文章,写的真的好; 《【翻译】Hy...
    JiMingQiang阅读 5,039评论 0 7
  • 在一个方法内部定义的变量都存储在栈中,当这个函数运行结束后,其对应的栈就会被回收,此时,在其方法体中定义的变量将不...
    Y了个J阅读 9,870评论 1 14
  • 我想 我是真的害羞了 不然 为何有一块布 (那三个品成的菱形 和那熟悉的顶灯呀 只有用一块布 稍释我的中华之心)
    半个读书人阅读 1,885评论 6 24