上一篇说了关于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 {@Overridepublic  Callable wrapCallable(final Callable callable) {// 使用阿里的 TtlCallable 重新包一层,解决线程间数据传递问题// return TtlCallable.get(callable);// 使用自定义的包装对象,将当前mdc复制到Hystrix新线程中return ThreadMdcUtil.wrap(callable, MDC.getCopyOfContextMap());}}

注册我们的RequestContextHystrixConcurrencyStrategy策略到Hystrix

@Configuration@Slf4jpublic class HystrixCircuitBreakerConfiguration {@PostConstructpublic void init() {HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestContextHystrixConcurrencyStrategy());}}

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

作者:仓储大叔,张占岭,
荣誉:微软MVP
QQ:853066980

支付宝扫一扫,为大叔打赏!