Sleuth 信息在线程之间的传递

Stella981
• 阅读 684

1. 问题

上期说,_Sleuth作为微服务下的调用链框架,支持traceId在各种多线程情况下的传递_。很抱歉,这个结论是错的,我在这里向大家道歉

2. 分析

得出这个结论是因为官方文档的一句话链接

We’re providing LazyTraceExecutor, TraceableExecutorService and TraceableScheduledExecutorService. Those implementations are creating Spans each time a new task is submitted, invoked or scheduled.

翻译:我们提供LazyTraceExecutor, TraceableExecutorService和TraceableScheduledExecutorService这三个实现类,以期在一个新线程任务提交、执行或调度时创建新的Span

这句话很有迷惑性,很容易让人误解(好吧我承认,目前只有我),认为Sleuth支持各种多线程。遗憾的是,如果你手动创建了一个Thread,调用下一级服务时,Sleuth并不能感知到

3. 证明

3.1 方法一

写个Demo看下,是否TraceId能够正常传过去

3.2 方法二

我们看下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并不稀奇,因为它根本就是要你使用它的多线程工具。

4.能否让子线程获取父线程信息呢

4.1 能:InheritableThreadLocal

一般来说,每个线程一个副本,我们都是用ThreaLocal。可是,如果你想要该线程和它的子线程都能读这个副本,那就可以用InheritableThreadLocal了。
用法很简单Demo

    private static final ThreadLocal<String> sessionInfoHolder1 = new ThreadLocal<String>();
    private static final ThreadLocal<String> sessionInfoHolder2 = new InheritableThreadLocal<String>();

5. 思考

既然Sleuth不支持用户自己创建线程,而使用InheritableThreadLocal可以解决这个问题,那么是不是说,Sleuth这个短板其实是可以解决的?

5.1 方案

  1. Filter中获取TraceId,存入:InheritableThreadLocal
  2. TraceFeignClient中判断当前线程或其父线程中是否有traceId,如果有,就证明是用户new的线程,即可复用Trace信息。
  3. 有兴趣的读者可以去Sleuth拉个分支试下,说不定会被管理员merge
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
添砖java的啾 添砖java的啾
3年前
distinct效率更高还是group by效率更高?
目录00结论01distinct的使用02groupby的使用03distinct和groupby原理04推荐groupby的原因00结论先说大致的结论(完整结论在文末):在语义相同,有索引的情况下groupby和distinct都能使用索引,效率相同。在语义相同,无索引的情况下:distinct效率高于groupby。原因是di
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
待兔 待兔
2个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
2年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
8个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这