Spring Boot 3.0.2微服务TraceId未从父服务传播至子服务求助
TraceId跨服务传播问题(Spring Boot 3.0.2 + Micrometer)
问题场景
父服务通过WebClient调用子服务时,子服务未接收到父服务的TraceId,而是生成了新的Observation对象,导致链路追踪断裂。
父服务调用代码
public Mono<Product> productFromIntegrator() { String url = "http://localhost:8282/product"; return Mono.deferContextual(contextView -> { try (ContextSnapshot.Scope scope = ContextSnapshot.setThreadLocalsFrom(contextView, ObservationThreadLocalAccessor.KEY)) { LOG.info("<ACCEPTANCE_TEST> <TRACE:{}> Hello from producer", tracer.currentSpan().context().traceId()); LOG.info("Service Called"); return webClient.get().uri(url) .retrieve().bodyToMono(Product.class).log(LOG.getName(), Level.FINE) .onErrorMap(WebClientException.class, ex -> { LOG.warn("Error retrieving Product"); return ex; }); } }); }
子服务Controller代码
@Autowired private final Service service; private final Tracer tracer; public Controller(Service service, Tracer tracer) { this.service = service; this.tracer = tracer; } @GetMapping(value = "/product") public Mono<Product> getProduct() { return Mono.deferContextual(contextView -> { try (ContextSnapshot.Scope scope = ContextSnapshot.setThreadLocalsFrom(contextView, ObservationThreadLocalAccessor.KEY)) { LOG.info("<ACCEPTANCE_TEST> <TRACE:{}> Hello from producer", tracer.currentSpan().context().traceId()); LOG.info("Service Called"); return this.service.getProduct(); } }); }
解决建议
1. 正确配置WebClient的Observation支持
Spring Boot 3.x中,WebClient需要绑定ObservationRegistry来自动传播Trace信息,让框架自动管理上下文:
@Bean public WebClient webClient(ObservationRegistry observationRegistry) { return WebClient.builder() .observationRegistry(observationRegistry) .build(); }
2. 移除手动ContextSnapshot处理代码
手动调用ContextSnapshot.setThreadLocalsFrom会干扰Reactor上下文的自动传播逻辑,Reactor会自动携带Observation信息,无需手动绑定线程本地变量。修改父服务代码:
public Mono<Product> productFromIntegrator() { String url = "http://localhost:8282/product"; LOG.info("<ACCEPTANCE_TEST> <TRACE:{}> Hello from producer", tracer.currentSpan().context().traceId()); LOG.info("Service Called"); return webClient.get().uri(url) .retrieve().bodyToMono(Product.class).log(LOG.getName(), Level.FINE) .onErrorMap(WebClientException.class, ex -> { LOG.warn("Error retrieving Product"); return ex; }); }
3. 子服务简化上下文处理
子服务的Controller无需手动处理ContextSnapshot,Spring WebFlux会自动从请求头中提取Trace信息并绑定到上下文:
@GetMapping(value = "/product") public Mono<Product> getProduct() { LOG.info("<ACCEPTANCE_TEST> <TRACE:{}> Hello from producer", tracer.currentSpan().context().traceId()); LOG.info("Service Called"); return this.service.getProduct(); }
4. 确保依赖完整
检查项目依赖是否包含Micrometer Trace核心组件:
Maven
<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-tracing-bridge-brave</artifactId> </dependency> <dependency> <groupId>io.zipkin.reporter2</groupId> <artifactId>zipkin-reporter-brave</artifactId> </dependency>
Gradle
implementation 'io.micrometer:micrometer-tracing-bridge-brave' implementation 'io.zipkin.reporter2:zipkin-reporter-brave'
5. 配置Trace传播格式
可通过配置文件指定Trace信息的传播格式(默认使用b3格式):
management: tracing: propagation: type: b3
6. 验证请求头传播
在父服务中添加日志,确认请求头是否携带X-B3-TraceId、X-B3-SpanId等Trace字段:
return webClient.get().uri(url) .exchangeToMono(response -> { LOG.info("Sent request headers: {}", response.request().headers()); return response.bodyToMono(Product.class); }) .onErrorMap(WebClientException.class, ex -> { LOG.warn("Error retrieving Product"); return ex; });
内容的提问来源于stack exchange,提问作者msuzuki
相关产品推荐
相关产品推荐

