Feign自定义header无法传递

2018-10-31  本文已影响0人  麦麦的生鱼片

问题描述

SpringCloud接入了Zipkin, 并使用header字段tid做为系统全局的traceId. 在入口中的tid已经被设置, 并放入MDC中, 但是在被调方无法拿到tid

排查过程

Feign在使用中接入了Hystrix, 所以考虑应该hystrix的问题, 排查中发现zipkin的参数X-B3-TraceId和X-B3-SpanId是可以找到的, 这就有点奇怪了.

tid排查

Hystrix使用线程隔离, 所以切换线程的时候, 必须显式的拷贝线程参数, 这个可以用HystrixConcurrencyStrategy来重写hystrix的提交时的操作, 达到拷贝变量的目的, 增加该配置后, tid可以在Feign发送动作中发现

public class HystrixConcurrencyStrategy extends com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy {
    private static final Logger LOGGER = LoggerFactory.getLogger(HystrixConcurrencyStrategy.class);

    @Override
    public <T> Callable<T> wrapCallable(final Callable<T> callable) {
        final Map context = MDC.getCopyOfContextMap();

        return new Callable<T>() {
            @Override
            public T call() {
                Map<String, String> original = MDC.getCopyOfContextMap();
                if (context != null) {
                    MDC.setContextMap(context);
                } else {
                    MDC.clear();
                }
                try {
                    return callable.call();
                } catch (Exception e) {
                    LOGGER.error("HttpCallCommand call failed.", e);
                    return null;
                } finally {
                    if (original != null) {
                        MDC.setContextMap(original);
                    } else {
                        MDC.clear();
                    }
                }
            }
        };

    }
}

Zipkin变量排查

既然tid无法做到跨线程, 那Zipkin是怎么做的呢? 同理也是使用了一样的做法, 在SleuthHystrixConcurrencyStrategy中, 将所有的调用Callable做一层包裹, 将需要的参数在调用前通过tracer.continueSpan(span)或者tracer.createSpan(HYSTRIX_COMPONENT)放到对应的MDC中, 达到传递参数的目的

// Visible for testing
    static class HystrixTraceCallable<S> implements Callable<S> {

        private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());

        private final Tracer tracer;
        private final TraceKeys traceKeys;
        private final Callable<S> callable;
        private final Span parent;

        public HystrixTraceCallable(Tracer tracer, TraceKeys traceKeys,
                Callable<S> callable) {
            this.tracer = tracer;
            this.traceKeys = traceKeys;
            this.callable = callable;
            this.parent = tracer.getCurrentSpan();
        }

        @Override
        public S call() throws Exception {
            Span span = this.parent;
            boolean created = false;
            if (span != null) {
                span = this.tracer.continueSpan(span);
                if (log.isDebugEnabled()) {
                    log.debug("Continuing span " + span);
                }
            }
            else {
                span = this.tracer.createSpan(HYSTRIX_COMPONENT);
                created = true;
                if (log.isDebugEnabled()) {
                    log.debug("Creating new span " + span);
                }
            }
            if (!span.tags().containsKey(Span.SPAN_LOCAL_COMPONENT_TAG_NAME)) {
                this.tracer.addTag(Span.SPAN_LOCAL_COMPONENT_TAG_NAME, HYSTRIX_COMPONENT);
            }
            String asyncKey = this.traceKeys.getAsync().getPrefix()
                    + this.traceKeys.getAsync().getThreadNameKey();
            if (!span.tags().containsKey(asyncKey)) {
                this.tracer.addTag(asyncKey, Thread.currentThread().getName());
            }
            try {
                return this.callable.call();
            }
            finally {
                if (created) {
                    if (log.isDebugEnabled()) {
                        log.debug("Closing span since it was created" + span);
                    }
                    this.tracer.close(span);
                }
                else if(this.tracer.isTracing()) {
                    if (log.isDebugEnabled()) {
                        log.debug("Detaching span since it was continued " + span);
                    }
                    this.tracer.detach(span);
                }
            }
        }
上一篇下一篇

猜你喜欢

热点阅读