zoukankan      html  css  js  c++  java
  • 全链路追踪traceId,ThreadLocal与ExecutorService

    关于全链路追踪traceId遇到线程池的问题,做过架构的估计都遇到过,现在以写个demo,总体思想就是获取父线程traceId,给子线程,子线程用完移除掉。

    mac上的chrome时不时崩溃,写了一大半的博客没了,直接贴源码和注释吧

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class ThreadPoolTracing {
    
        private static final Logger logger = LoggerFactory.getLogger(ThreadPoolTracing.class);
        public static ThreadLocal<String>  threadLocalTraceId = new ThreadLocal<>();
    
        static class Task implements Runnable {
    
            @Override
            public void run() {
                String traceId=threadLocalTraceId.get();
                logger.info("traceId={}",traceId);
            }
        }
    }
    public class MyTest2 {
    
        private static final Logger loger = LoggerFactory.getLogger(MyTest2.class);
        //线程池大小设置为一,保证是同一个线程run之前获取traceId,run后删除,便于测试
        private static ExecutorService executorService = Executors.newFixedThreadPool(1);
    
        @Test
        public void test1() {
    
            String traceId = UUID.randomUUID().toString().replace("-", "");
            ThreadPoolTracing.threadLocalTraceId.set(traceId);
            loger.info("父线程={};traceId={}",Thread.currentThread().getName(),traceId);
    
            Runnable runnable=new Runnable() {
                @Override
                public void run() {
                    //ThreadLocal 拿不到值;如果是InheritableThreadLocal,可以拿到值
                    String id0 = ThreadPoolTracing.threadLocalTraceId.get();
                    loger.info("子线程={},traceId={}",Thread.currentThread().getName(),id0);
                }
            };
            executorService.execute(runnable);//结果为空
            executorService.execute(new ThreadPoolTracing.Task());//结果为空
    
            Runnable wrap=  wrap( runnable);
            executorService.execute(wrap);//可以获取traceId
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            traceId = UUID.randomUUID().toString().replace("-", "");
            //traceId 重新复制
            ThreadPoolTracing.threadLocalTraceId.set(traceId);
            loger.info("父线程={};traceId={}",Thread.currentThread().getName(),traceId);
            //线程池中的traceId跟着变更
            wrap=  wrap( runnable);
            executorService.execute(wrap);
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    
       
        public Runnable wrap(Runnable task) {
            //获取父线程中的Trace
            String id0 = ThreadPoolTracing.threadLocalTraceId.get();
            class CurrentTraceContextRunnable implements Runnable {
                @Override
                public void run() {
                    //traceId 给子线程
                    ThreadPoolTracing.threadLocalTraceId.set(id0);
                    task.run();
                    //子线程用完删除
                    ThreadPoolTracing.threadLocalTraceId.remove();
                }
            }
            return new CurrentTraceContextRunnable();
    
        }
    
    
    }
  • 相关阅读:
    python 模块和包以及他们的导入关系
    python time,random,os,sys,序列化模块
    python 可迭代对象,迭代器和生成器,lambda表达式
    python之拷贝(深浅)
    python 内置函数
    python 函数的递归
    python 装饰器
    python 函数基础知识整理
    @清晰掉 string.h之基础堵漏
    C和C++之间库的互相调用
  • 原文地址:https://www.cnblogs.com/zhangzhi19861216/p/10342882.html
Copyright © 2011-2022 走看看