• 全链路追踪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();
    
        }
    
    
    }
  • 相关阅读:
    高性能网站优化——兼容
    高性能网站优化——开发
    leetcode刷题日记: 19.删除链表的倒数第k个节点
    大数据处理技术学习
    <java复习>返回可变对象引用的get方法要点
    <C++网络编程随笔>常用Socket函数总结
    <leetcode每日一题>数组中的第K个最大元素
    <leetcode每日一题>二叉树的LCA查找
    codeforce round615 div3 B
    暑假作业竟然如此芳香(hdu4145枚举+贪心)
  • 原文地址:https://www.cnblogs.com/zhangzhi19861216/p/10342882.html
Copyright © 2020-2023  润新知