如何在Spring Boot微服务/REST API间传播traceId与spanId?
实现TraceId/SpanId跨REST API传播的方案
下面针对Spring Boot环境下,基于Micrometer Tracing的trace信息传播,提供几种具体实现方式:
1. 确保依赖配置正确
首先确认项目中已引入Micrometer Tracing相关依赖,比如使用Brave作为桥接实现:
<!-- Maven依赖 --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-tracing-bridge-brave</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
或Gradle配置:
implementation 'io.micrometer:micrometer-tracing-bridge-brave' implementation 'org.springframework.boot:spring-boot-starter-web'
2. 使用RestTemplate自动传播(推荐)
Spring会自动为通过RestTemplateBuilder创建的RestTemplate添加追踪拦截器,自动将traceId/spanId以标准头格式(默认B3,可配置为W3C)注入请求中。
方式一:注入自动配置的RestTemplate
@Service public class YourService { private final RestTemplate restTemplate; // 注入Spring自动配置的RestTemplate public YourService(RestTemplate restTemplate) { this.restTemplate = restTemplate; } public void callExternalApi() { // 发起请求时,trace头会自动添加 ResponseEntity<String> response = restTemplate.getForEntity( "http://external-service/api/resource", String.class ); } }
方式二:自定义RestTemplate(通过RestTemplateBuilder)
如果需要自定义RestTemplate,必须通过RestTemplateBuilder构建,才能带上追踪拦截器:
@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder // 可添加自定义配置,比如消息转换器 .build(); } }
3. 使用WebClient自动传播(适用于响应式场景)
对于响应式WebClient,Spring同样会自动添加追踪过滤器,实现trace信息传播:
@Service public class ReactiveService { private final WebClient webClient; public ReactiveService(WebClient.Builder webClientBuilder) { this.webClient = webClientBuilder.baseUrl("http://external-service").build(); } public Mono<String> fetchExternalData() { return webClient.get() .uri("/api/resource") .retrieve() .bodyToMono(String.class); } }
4. 手动传播(适用于非Spring原生HTTP客户端)
如果使用OkHttp、原生HttpURLConnection等第三方客户端,需要手动从Tracer中提取trace信息,添加到请求头:
示例:使用OkHttp手动添加B3格式头
@Service public class ManualTracePropagationService { private final Tracer tracer; private final OkHttpClient okHttpClient; public ManualTracePropagationService(Tracer tracer) { this.tracer = tracer; this.okHttpClient = new OkHttpClient(); } public String callApiManually() throws IOException { TraceContext currentContext = tracer.currentTraceContext().context(); Request request = new Request.Builder() .url("http://external-service/api/resource") // B3格式标准头 .addHeader("X-B3-TraceId", currentContext.traceId()) .addHeader("X-B3-SpanId", currentContext.spanId()) .addHeader("X-B3-Sampled", currentContext.sampled() ? "1" : "0") // 若使用W3C Traceparent格式,替换为以下头 // .addHeader("traceparent", String.format("00-%s-%s-%s", // currentContext.traceId(), // currentContext.spanId(), // currentContext.sampled() ? "01" : "00")) .build(); try (Response response = okHttpClient.newCall(request).execute()) { return response.body().string(); } } }
5. 配置传播格式(可选)
默认使用B3格式,若需切换为W3C Traceparent,可在application.yml中配置:
micrometer: tracing: propagation: type: W3C
内容的提问来源于stack exchange,提问作者Rodrigo López Gatica
相关产品推荐
相关产品推荐

