1 前言
1.1 什么是 TraceId?
TraceId
是一個唯一的標識符,用于跟蹤分布式系統中的請求。每個請求從客戶端發起到服務端處理,再到可能的多個微服務調用,都會攜帶這個 TraceId
,以便在整個請求鏈路中進行追蹤和調試。
1.2 日志鏈路追蹤的意義
日志鏈路追蹤可以幫助開發者:
- 快速定位問題:通過
TraceId
關聯所有相關日志,快速找到問題的根源。 - 性能分析:分析請求在各個服務中的耗時,優化性能瓶頸。
- 監控系統狀態:實時監控系統的運行狀態,確保系統的穩定性和可靠性。
1.3 適用場景
- 微服務架構:多個服務之間的調用需要追蹤。
- 分布式系統:跨多個節點的請求需要追蹤。
- 復雜業務流程:需要追蹤請求在各個步驟中的處理情況。
2 環境準備
2.1 Spring Boot 版本要求
本文基于 Spring Boot 2.7.x 版本進行編寫,其他版本可能需要調整依賴和配置。
2.2 引入依賴(Sleuth 或 MDC)
2.2.1 使用 Sleuth
Sleuth 是 Spring Cloud Sleuth 的一部分,可以自動為每個請求生成 TraceId
和 SpanId
,并將其注入到日志中。
在 pom.xml
中添加以下依賴:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
2.2.2 使用 MDC
MDC(Mapped Diagnostic Context)是 Logback 提供的一個工具,可以將上下文信息(如 TraceId
)綁定到當前線程,方便在日志中輸出。
在 pom.xml
中添加以下依賴:
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId>
</dependency>
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId>
</dependency>
2.3 配置日志格式
2.3.1 使用 Sleuth
Sleuth 默認會將 TraceId
和 SpanId
注入到日志中,無需額外配置。
2.3.2 使用 MDC
在 logback-spring.xml
中配置日志格式,添加 %X{traceId}
以輸出 TraceId
:
<configuration><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - [%X{traceId}] %msg%n</pattern></encoder></appender><root level="info"><appender-ref ref="STDOUT" /></root>
</configuration>
3 實現步驟
3.1 自動生成 TraceId
3.1.1 使用 Sleuth 自動生成 TraceId
Sleuth 會自動為每個請求生成 TraceId
和 SpanId
,無需額外代碼。
3.1.2 自定義 TraceId 生成邏輯
如果需要自定義 TraceId
生成邏輯,可以實現 TraceIdProvider
接口:
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer.TraceIdProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.UUID;@Configuration
public class TraceIdConfig {@Beanpublic TraceIdProvider traceIdProvider() {return new TraceIdProvider() {@Overridepublic String nextTraceId() {return UUID