traceId实现
普通
内部拦截器,threadlocal变量set上下文context。
父子线程传递
InheritableThreadLocal
Thread内部为InheritableThreadLocal开辟了一个单独的ThreadLocalMap。在父线程创建一个子线程的时候,会检查这个ThreadLocalMap是否为空,不为空则会浅拷贝给子线程的ThreadLocalMap。
线程池场景传递
TransmittableThreadLocal,有个专门的TtlRunnable和TtlCallable包装类,用于读取原Thread的ThreadLocal对象及值并存于Runnable/Callable中,在执行run或者call方法的时候再将存于Runnable/Callable中的ThreadLocal对象和值读取出来,存入调用run或者call的线程中。
public void testAsync() { ExecutorService ttlExecutorService = TtlExecutors.getTtlExecutorService(executorService); String traceId = Tracer.startServer(); //父线程的traceId ThreadLocal<String> traceContext = new TransmittableThreadLocal<>(); traceContext.set(traceId); //存入TransmittableThreadLocal ttlExecutorService.submit(new Runnable() { @Override public void run() { //runnable执行中获取当前线程的traceId与父线程的traceId一致 String childTraceId = traceContext.get(); Assert.assertEquals(childTraceId, traceId); Tracer.startClient(traceId); Tracer.endClient(); } }); Tracer.endServer(); }
考虑到代码入侵,可以通过-javaagent:/xx/transmittable-thread-local.jar启动,对原生类进行字节码增强。提交的java.lang.Runnable类型的任务会被包装为TtlRunnable,提交的java.util.concurrent.Callable类型的任务会被包装为TtlCallable,实现了无入侵无感知地嵌入TTL的功能。
TtlExecutorTransformlet处理的类:ThreadPoolExecutor及其子类、ScheduledThreadPoolExecutor。
TtlForkJoinTransformlet处理的类:ForkJoinTask、ForkJoinPool 默认开启。
TtlTimerTaskTransformlet处理的类:仅处理TimeTask子类。