在分布式链路跟踪系统中,同一条请求处理链路要用一个全局唯一的 traceId 来标识,那就需要把 traceId 传输到该请求涉及的各个系统中。Trace 信息要在系统之间传输时,是通过各种 RPC 中间件里埋点,把 Trace 信息放在 HTTP Header、RPC Context 里进行传输的。
实际中,同一个系统内部业务处理出现多线程操作时,如果不做显式处理,也容易丢失 Trace 信息。那么遇到跨线程操作时,怎么做才能保证 Trace 信息不丢失呢?可以参考阿里开源的 transmittable-thread-local,基本原理是在创建 Runnable 或 Callabke 的时候,把父线程的 Trace 数据存起来传递给子线程,子线程执行之前先获取 Trace 数据设置 Context,再执行业务代码,具体可以看 TtlRunnable 类:
public final class TtlRunnable implements Runnable, TtlEnhanced, TtlAttachments {
private final AtomicReference<Object> capturedRef; // 需要跨线程传输的数据
private final Runnable runnable; // 待执行的 Runnable
private TtlRunnable(@NonNull Runnable runnable) {
this.capturedRef = new AtomicReference<Object>(capture()); // 获取主线程的 Context 信息
this.runnable = runnable;
}
/**
* wrap method {@link Runnable#run()}.
*/
@Override
public void run() {
Object captured = capturedRef.get();
Object backup = replay(captured); // 设置 Context,并返回线程中原先已有的 Context 数据
try {
runnable.run(); // 执行业务代码
} finally {
restore(