上一篇说了关于MDC跨线程为null的理解,而本讲主要说一下,如何去解决它,事实上,Hystrix为我们留了这个口,我们只需要继承HystrixConcurrencyStrategy,然后重写wrapCallable方法,再把这个重写的对象注册到Hystrix里就可以了,跨线程共享数据,可以使用阿里的 transmittable-thread-local组件,如果只是共离MDC的话,可以自己写个组件就行。

一 ThreadMdcUtil用来同步MDC对象

public class ThreadMdcUtil {

public static Callable wrap(final Callable callable, final Map context) {

return () -> {

if (context == null) {

MDC.clear();

}

else {

MDC.setContextMap(context);

}

try {

return callable.call();

}

finally {

MDC.clear();

}

};

}

public static Runnable wrap(final Runnable runnable, final Map context) {

return () -> {

if (context == null) {

MDC.clear();

}

else {

MDC.setContextMap(context);

}

try {

runnable.run();

}

finally {

MDC.clear();

}

};

}

}

重写HystrixConcurrencyStrategy,将主线程的MDC传入Hystrix建立的新线程

/**

* 线程上下文传递,hystrix的相关实现有兴趣可以看源码, hystrix提供了这个口子可以处理线程间传值问题,这里不做过多赘述

*/

public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {

@Override

public Callable wrapCallable(final Callable callable) {

// 使用阿里的 TtlCallable 重新包一层,解决线程间数据传递问题

// return TtlCallable.get(callable);

// 使用自定义的包装对象,将当前mdc复制到Hystrix新线程中

return ThreadMdcUtil.wrap(callable, MDC.getCopyOfContextMap());

}

}

注册我们的RequestContextHystrixConcurrencyStrategy策略到Hystrix

@Configuration

@Slf4j

public class HystrixCircuitBreakerConfiguration {

@PostConstruct

public void init() {

HystrixPlugins.getInstance().registerConcurrencyStrategy(

new RequestContextHystrixConcurrencyStrategy());

}

}

运行结果,使用openFeign时,已经共享了traceId这个数据值

好文链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。