Java分布式链路API怎么集成

wen java案例 1

本文目录导读:

Java分布式链路API怎么集成

  1. OpenTelemetry集成方案(推荐)
  2. Spring Cloud Sleuth集成方案
  3. 自定义链路上下文传递
  4. 消息队列链路传递
  5. 最佳实践建议
  6. 集成测试示例
  7. 注意事项

我将为您详细讲解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();
    }
}

注意事项

  1. 性能影响:合理设置采样率,避免全量采样
  2. 数据安全:不要在Span属性中记录敏感信息
  3. 版本兼容:确保依赖版本与Spring Boot版本兼容
  4. 存储规划:规划好链路数据的存储方案(ES、Cassandra等)

选择合适的方案时,建议优先考虑OpenTelemetry,因为它已成为CNCF的标准化项目,具有更好的生态和发展前景。

上一篇Java分布式配置管理API用Apollo吗

下一篇当前分类已是最新一篇

抱歉,评论功能暂时关闭!