调用链追踪(Trace ID)

ops/2025/3/5 12:25:37/

前言:

在 Java 中实现 调用链追踪(Trace ID) 通常用于分布式系统中跟踪请求的完整链路,常见的实现方式包括手动编码或使用开源框架(如 SkyWalkingZipkinSpring Cloud Sleuth 等)。以下是具体实现方法及示例:

1. 手动实现 Trace ID

通过 ThreadLocal 或 MDC(Mapped Diagnostic Context)存储 Trace ID,并在请求链路中传递。

步骤 1:定义 Trace ID 工具类
java">import org.slf4j.MDC;
import java.util.UUID;public class TraceIdUtil {private static final String TRACE_ID_KEY = "traceId";private static final ThreadLocal<String> traceIdHolder = new ThreadLocal<>();// 生成或获取当前 Trace IDpublic static String getOrGenerateTraceId() {String traceId = MDC.get(TRACE_ID_KEY);if (traceId == null) {traceId = UUID.randomUUID().toString().replace("-", "");MDC.put(TRACE_ID_KEY, traceId);traceIdHolder.set(traceId);}return traceId;}// 清除 Trace ID(防止内存泄漏)public static void clear() {MDC.remove(TRACE_ID_KEY);traceIdHolder.remove();}
}

步骤 2:在 HTTP 请求中传递 Trace ID

通过拦截器在请求头中添加 Trace ID:

java">import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;public class TraceIdInterceptor implements ClientHttpRequestInterceptor {@Overridepublic ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {String traceId = TraceIdUtil.getOrGenerateTraceId();request.getHeaders().add("X-Trace-Id", traceId);return execution.execute(request, body);}
}

步骤 3:在日志中输出 Trace ID

配置 logback.xml,在日志模板中添加 %X{traceId}

<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n</pattern>

2. 使用 Spring Cloud Sleuth + Zipkin(推荐)

Spring Cloud Sleuth 自动集成 Trace ID,Zipkin 提供可视化追踪。

步骤 1:添加依赖
<!-- Spring Cloud Sleuth -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency><!-- Zipkin 上报 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
步骤 2:配置 application.yml

java">spring:sleuth:sampler:probability: 1.0  # 采样率(1.0=100%上报)zipkin:base-url: http://localhost:9411  # Zipkin 服务地址
 
步骤 3:查看调用链

启动 Zipkin 服务后,访问 http://localhost:9411 查看完整的调用链路。


3. 使用 SkyWalking

SkyWalking 是一款开源的 APM 系统,支持自动链路追踪。

步骤 1:下载并启动 SkyWalking

# 下载 SkyWalking
wget https://archive.apache.org/dist/skywalking/9.6.0/apache-skywalking-apm-9.6.0.tar.gz
tar -zxvf apache-skywalking-apm-9.6.0.tar.gz
cd apache-skywalking-apm-bin# 启动 SkyWalking
bin/startup.sh
 
步骤 2:Java 应用接入 Agent

在 JVM 启动参数中添加 Agent:

-javaagent:/path/to/skywalking-agent/skywalking-agent.jar
-Dskywalking.agent.service_name=your-service-name
-Dskywalking.collector.backend_service=localhost:11800
 

4. 异步线程传递 Trace ID

使用 TransmittableThreadLocal 解决线程池中 Trace ID 丢失问题:

java">import com.alibaba.ttl.TransmittableThreadLocal;public class TraceContext {private static final TransmittableThreadLocal<String> traceIdHolder = new TransmittableThreadLocal<>();public static void setTraceId(String traceId) {traceIdHolder.set(traceId);}public static String getTraceId() {return traceIdHolder.get();}public static void clear() {traceIdHolder.remove();}
}// 在线程池任务中调用
ExecutorService executor = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(10));
executor.submit(() -> {System.out.println("Trace ID: " + TraceContext.getTraceId());
});
 

关键点总结

方案适用场景优点缺点
手动实现 Trace ID简单项目或框架不支持链路追踪时轻量级,无依赖需自行处理传递逻辑
Spring Cloud SleuthSpring Cloud 微服务项目自动化集成,支持 Zipkin 可视化依赖 Spring 生态
SkyWalking企业级监控,多语言支持功能强大,支持全链路追踪需部署额外服务

根据项目需求选择合适方案!


http://www.ppmy.cn/ops/163296.html

相关文章

AI企业流程自动化(BPA - Business Process Automation)

目前市场上确实有一些 AI 解决方案&#xff0c;能够覆盖公司多个业务流程&#xff0c;实现 端到端的企业流程自动化&#xff08;BPA - Business Process Automation&#xff09;。不过&#xff0c;想要 完全自动化所有岗位&#xff08;财务、出纳、管理、产品、研发、销售、营销…

系统架构设计师—软件工程基础篇—系统运维与维护

文章目录 软件维护分类遗留系统 软件维护分类 在系统运行过程中&#xff0c;软件需要维护的原因是多样的。根据维护的原因不同&#xff0c;可以讲软件维护分为以下4种&#xff1a; 改正性维护 修改软件错误、改正软件性能上的缺点、排除实施中的错误使用。 适应性维护 在使用…

表达式求值(后缀表达式)

后缀表达式 后缀表达式是给计算机去看的,一个个压进栈中; 遇到操作符就计算再将计算出的结果压到栈中;最后弹出结果。 1.栈的初始化(动态存储) typedef struct {ElemType* data;int top; }Stack; //初始化 Stack* initStack() {Stack* s (Stack*)malloc(sizeof(Stack));s->…

【蓝桥】常用库函数

1、memset()函数 1.1 基本介绍 定义在头文件<cstring>中主要作用是对一块内存区域进行设置值的操作 1.2 函数原型 void *memset(void *str, int c, size_t n);str&#xff1a;指向要填充的内存块的指针c&#xff1a;要设置的值。该值以int形式传递&#xff0c;但函数在…

玩转顺序表:用 C 语言实现数据的插入与删除

目录 顺序表的定义 插入元素 删除元素 查找元素 主函数 打印顺序表 完整代码 总结 在这篇博客中&#xff0c;我们将探讨如何使用 C 语言实现一个简单的顺序表&#xff08;也称为动态数组&#xff09;&#xff0c;并实现一些基本操作&#xff0c;包括插入、删除和查找…

ldap放大 DDOS.c

ldap放大汉化源码 安装环境指令: 乌班图/Debian系统: apt install gcc -y centos系统: yum install gcc -y 编译指令: gcc ldap.c -o ldap -pthread -stdgnu99 最后输入 ./ldap 查看使用方法 注意:本脚本完全开源免费,请勿使用任何已编译版本,使用本脚本必须拥有roo…

京东一面:为什么 IDEA 建议去掉 StringBuilder,而要使用 “+” 拼接字符串?

本文已收录至Java面试网站&#xff1a;https://topjavaer.cn 今天咱们来聊聊一个很常见的开发场景&#xff1a;字符串拼接。在日常开发中&#xff0c;字符串拼接几乎是每个 Java 开发者都会用到的操作。但最近&#xff0c;有朋友在面试时被问到一个问题&#xff1a;“为什么 ID…

Zookeeper 及 基于ZooKeeper实现的分布式锁

1 ZooKeeper 1.1 ZooKeeper 介绍 ZooKeeper是一个开源的分布式协调服务&#xff0c;它的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来&#xff0c;构成一个高效可靠的原语集&#xff0c;并以一系列简单易用的接口提供给用户使用。 原语&#xff1a;操作系统或…