上期說,Sleuth做爲微服務下的調用鏈框架,支持traceId在各類多線程狀況下的傳遞。很抱歉,這個結論是錯的,我在這裏向你們道歉html
得出這個結論是由於官方文檔的一句話連接:java
We’re providing LazyTraceExecutor, TraceableExecutorService and TraceableScheduledExecutorService. Those implementations are creating Spans each time a new task is submitted, invoked or scheduled.git
翻譯:咱們提供LazyTraceExecutor, TraceableExecutorService和TraceableScheduledExecutorService這三個實現類,以期在一個新線程任務提交、執行或調度時建立新的Spangithub
這句話頗有迷惑性,很容易讓人誤解(好吧我認可,目前只有我),認爲Sleuth支持各類多線程。遺憾的是,若是你手動建立了一個Thread,調用下一級服務時,Sleuth並不能感知到spring
寫個Demo看下,是否TraceId可以正常傳過去session
咱們看下LazyTraceExecutor是怎麼作的多線程
public class LazyTraceExecutor implements java.util.concurrent.Executor { private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); private Tracer tracer; private final BeanFactory beanFactory; private final Executor delegate; private TraceKeys traceKeys; private SpanNamer spanNamer; public LazyTraceExecutor(BeanFactory beanFactory, Executor delegate) { this.beanFactory = beanFactory; this.delegate = delegate; } @Override public void execute(Runnable command) { if (this.tracer == null) { try { this.tracer = this.beanFactory.getBean(Tracer.class); } catch (NoSuchBeanDefinitionException e) { this.delegate.execute(command); return; } } this.delegate.execute(new SpanContinuingTraceRunnable(this.tracer, traceKeys(), spanNamer(), command)); } }
使用方式框架
@Configuration public class MyConfiguration { @Autowired BeanFactory beanFactory; @Bean public Executor executor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // CUSTOMIZE HERE executor.setCorePoolSize(7); executor.setMaxPoolSize(42); executor.setQueueCapacity(11); executor.setThreadNamePrefix("MyExecutor-"); // DON'T FORGET TO INITIALIZE executor.initialize(); return new LazyTraceExecutor(this.beanFactory, executor); } }
因此它能在線程之間傳遞traceId並不稀奇,由於它根本就是要你使用它的多線程工具。ide
通常來講,每一個線程一個副本,咱們都是用ThreaLocal。但是,若是你想要該線程和它的子線程都能讀這個副本,那就能夠用InheritableThreadLocal了。
用法很簡單Demo:微服務
private static final ThreadLocal<String> sessionInfoHolder1 = new ThreadLocal<String>(); private static final ThreadLocal<String> sessionInfoHolder2 = new InheritableThreadLocal<String>();
既然Sleuth不支持用戶本身建立線程,而使用InheritableThreadLocal能夠解決這個問題,那麼是否是說,Sleuth這個短板實際上是能夠解決的?