SkyWalking8.4监控跨线程问题解决

在这里插入图片描述

一. 异步多线程问题

首先,Skywalking是一款基于java代理的监控系统,但是在监控多线程跨线程的时候却会意外失联,这就让我们没办法去追踪调用链路问题

类似于下图

@GetMapping("/task1")
    public CommonReturnType task1() throws Exception {

        for (int i = 0; i < 5; i++) {
            new Thread(()->{
                log.info("1");
            });
        }
        return CommonReturnType.creat(1);
    }

在这里插入图片描述
当然,只是为了演示简单,就没有写异步多线程,SkyWalking默认情况下只会采集同一线程的调用链路,如果应用里面采用了多线程,同时希望追踪链路能将多个线程的链路关联起来。则需要使用插件apm-toolkit-trace,下面通过一个小Demo来进行演示

添加依赖
	<dependency>
      <groupId>org.apache.skywalking</groupId>
      <artifactId>apm-toolkit-trace</artifactId>
      <version>8.4.0</version>
   </dependency>
开启异步多线程

主动启动类添加

@SpringBootApplication
@EnableAsync
public class IotMain8239 {
    public static void main( String[] args )
    {
        SpringApplication.run(IotMain8239.class,args);
    }
}
测试类方法


import com.fehead.Iot.mapper.GwKkkTest1Mapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.apache.skywalking.apm.toolkit.trace.RunnableWrapper;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import org.apache.skywalking.apm.toolkit.trace.TraceCrossThread;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Component
@Slf4j
public class HelloTask {

    @Autowired
    GwKkkTest1Mapper gwKkkTest1Mapper;

    ExecutorService executorService = Executors.newCachedThreadPool();

    @Async
    public void asynchelloWorld(){
        try {
            Thread.sleep(5000);

            //插入数据库用户
            GwKkkTest1 gwKkkTest1 = new GwKkkTest1(40000, "s", "s", "s");

            executorService.submit(RunnableWrapper.of(()->{
                gwKkkTest1Mapper.insert(gwKkkTest1);
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Optional<String> value = TraceContext.getCorrelation("key");  //拿到同一链路的指定key
                log.info("down : insert1 + " +value.get());
            }) );
            executorService.submit(RunnableWrapper.of(()->{
                gwKkkTest1Mapper.insert(gwKkkTest1);
                try {
                    Thread.sleep(7000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Optional<String> value = TraceContext.getCorrelation("jia"); //拿到同一链路的指定key
                log.info("down : insert2 + " +value.get());
            }) );

            log.info("down : HelloTask");

//            ActiveSpan.tag("intask", "王凯艺"); 打标记k,v
        }catch (Exception e){
            e.printStackTrace();
        }
    }


}

Controller层处理
@Autowired
    HelloTask helloTask;

    @GetMapping("/task")
    public CommonReturnType task() throws Exception {
        ActiveSpan.tag("type", "异步任务多线程任务");
        log.info("come in : /task");
        TraceContext.putCorrelation("key", "kaikai");
        TraceContext.putCorrelation("jia", "jiajia");
        helloTask.asynchelloWorld();
        return CommonReturnType.creat(1);
    }
  • 我们可以通过 ActiveSpan.tag(“type”, “异步任务多线程任务”) 去追踪里面添加相应的标签指定K-V
  • 在跟踪方法的上下文中添加自定义标签ActiveSpan.tag(“key”, “val”)。
  • ActiveSpan.error() 将当前范围标记为错误状态。
  • ActiveSpan.error(String errorMsg) 通过消息将当前范围标记为错误状态。
  • ActiveSpan.error(Throwable throwable) 使用Throwable将当前范围标记为错误状态。
  • ActiveSpan.debug(String debugMsg) 在当前范围中添加调试级别日志消息。
  • ActiveSpan.info(String infoMsg) 在当前范围内添加信息级别日志消息。
  • ActiveSpan.setOperationName(String operationName) 自定义操作名称。

在这里插入图片描述

  • 再来查看控制台发现已经打印出异步多线程的路线了,并且追踪ID相同
    在这里插入图片描述
分析

主要添加RunnableWrapper.of()来指定跟踪线程

  executorService.submit(RunnableWrapper.of(()->{
                gwKkkTest1Mapper.insert(gwKkkTest1);
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Optional<String> value = TraceContext.getCorrelation("key");  //拿到同一链路的指定key
                log.info("down : insert1 + " +value.get());
            }) );

也可以添加其他多线程方法

CallableWrapper.of()
CompletableFuture.supplyAsync(() ->{});

也可以添加指定实现多线程的类上注解 @TraceCrossThread

    @TraceCrossThread
    public static class MyTask<String> implements Callable<String> {}
       

二. 指定跟踪上下文的K-V

类似于ThreadLocal

使用TraceContext.putCorrelation()API将自定义数据放在跟踪上下文中。

Optional<String> previous = TraceContext.putCorrelation("customKey", "customValue");

当值是null或为空时,CorrelationContext将删除该项目。

Optional<String> value = TraceContext.getCorrelation("customKey");

使用TraceContext.getCorrelation()API获取自定义数据。

在这里插入图片描述

制作不易,求一个点赞+关注~~

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值