本文目录导读:

我将为您详细讲解Java分布式链路追踪API的集成方法,主要涉及最流行的OpenTelemetry和Spring Cloud Sleuth方案。
OpenTelemetry集成方案(推荐)
添加依赖
<!-- Spring Boot Starter -->
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.31.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
<version>1.31.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
<version>1.31.0</version>
</dependency>
<!-- Spring Boot 自动配置 -->
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-spring-boot-starter</artifactId>
<version>1.31.0-alpha</version>
</dependency>
配置属性
# application.yml
opentelemetry:
exporter:
otlp:
endpoint: http://localhost:4318 # OTLP接收端
traces:
sampler: parentbased_always_on
resource:
attributes:
service.name: my-service
service.version: 1.0.0
创建Tracer
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Tracer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TelemetryConfig {
@Autowired
private OpenTelemetry openTelemetry;
@Bean
public Tracer tracer() {
return openTelemetry.getTracer("com.example.tracer");
}
}
手动创建Span
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
@Autowired
private Tracer tracer;
public void processOrder(Long orderId) {
Span span = tracer.spanBuilder("processOrder")
.setAttribute("order.id", orderId)
.setAttribute("order.amount", 100.50)
.startSpan();
try (Scope scope = span.makeCurrent()) {
// 业务逻辑
Thread.sleep(100);
span.addEvent("Order processed successfully");
} catch (Exception e) {
span.recordException(e);
throw e;
} finally {
span.end();
}
}
}
使用注解(AOP方式)
import io.opentelemetry.instrumentation.annotations.WithSpan;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@WithSpan("createUser")
public User createUser(String username) {
// 方法会自动创建Span
return new User(username);
}
}
Spring Cloud Sleuth集成方案
添加依赖
<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>
配置属性
spring:
sleuth:
sampler:
probability: 1.0 # 采样率
web:
skip-pattern: /actuator/.* # 跳过某些路径
zipkin:
base-url: http://localhost:9411
sender:
type: web # 或 kafka, rabbit, activeMQ
自动注入Tracer
import brave.Tracer;
import brave.Span;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PaymentService {
@Autowired
private Tracer tracer;
public void processPayment(Long orderId) {
Span span = tracer.nextSpan().name("processPayment").start();
try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
span.tag("order.id", String.valueOf(orderId));
span.annotate("Payment started");
// 业务逻辑
Thread.sleep(50);
span.annotate("Payment completed");
} catch (Exception e) {
span.error(e);
throw e;
} finally {
span.finish();
}
}
}
异步任务支持
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import brave.Tracer;
@Service
public class AsyncService {
@Async
@NewSpan("asyncTask")
public Future<String> asyncMethod() {
// 自动创建新的Span
return CompletableFuture.completedFuture("Async result");
}
}
自定义链路上下文传递
创建线程池包装器
import brave.Tracing;
import brave.propagation.TraceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
public class TraceAwareThreadPool extends ThreadPoolTaskExecutor {
@Autowired
private Tracing tracing;
@Override
public void execute(Runnable task) {
TraceContext context = tracing.currentTraceContext().get();
super.execute(() -> {
try (Tracer.SpanInScope ws =
tracing.tracer().withSpanInScope(context)) {
task.run();
}
});
}
}
HTTP请求传递Trace
import org.springframework.web.client.RestTemplate;
import brave.spring.web.TracingClientHttpRequestInterceptor;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(Tracing tracing) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(
List.of(TracingClientHttpRequestInterceptor.create(tracing))
);
return restTemplate;
}
}
消息队列链路传递
Kafka消息传递
import org.springframework.kafka.core.KafkaTemplate;
import brave.kafka.clients.KafkaTracing;
@Service
public class KafkaTracingService {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
@Autowired
private KafkaTracing kafkaTracing;
public void sendWithTrace(String topic, String message) {
ProducerRecord<String, String> record =
new ProducerRecord<>(topic, message);
ProducerRecord<String, String> tracedRecord =
kafkaTracing.inject(record);
kafkaTemplate.send(tracedRecord);
}
}
最佳实践建议
采样策略配置
opentelemetry:
traces:
sampler:
type: parentbased_ratelimiting
rate: 10 # 每秒10个Span
Span标记最佳实践
@Service
public class BestPracticeService {
@WithSpan
public void businessMethod(String userId) {
Span span = Span.current();
// 添加业务标签
span.setAttribute("user.id", userId);
span.setAttribute("operation.type", "business");
// 记录异常
try {
dangerousOperation();
} catch (Exception e) {
span.setStatus(StatusCode.ERROR);
span.recordException(e);
}
}
}
集成监控端点
management:
endpoints:
web:
exposure:
include: health,info,metrics,traces
metrics:
export:
otlp:
enabled: true
集成测试示例
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import io.opentelemetry.api.trace.Span;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
class TracingIntegrationTest {
@Autowired
private Tracer tracer;
@Test
void testTraceCreation() {
Span span = tracer.spanBuilder("test-span")
.startSpan();
assertThat(span).isNotNull();
assertThat(span.getSpanContext().isValid()).isTrue();
span.end();
}
}
注意事项
- 性能影响:合理设置采样率,避免全量采样
- 数据安全:不要在Span属性中记录敏感信息
- 版本兼容:确保依赖版本与Spring Boot版本兼容
- 存储规划:规划好链路数据的存储方案(ES、Cassandra等)
选择合适的方案时,建议优先考虑OpenTelemetry,因为它已成为CNCF的标准化项目,具有更好的生态和发展前景。