从Spring Cloud Sleuth切换到Micrometer后,Spring Cloud Gateway中Tracer.getCurrentSpan()为何失效?
问题原因及解决方案
核心原因
过滤器执行顺序过早
Spring Cloud Gateway中负责初始化Trace Span的TraceWebFilter默认优先级为Ordered.HIGHEST_PRECEDENCE + 10,如果你的自定义全局过滤器执行顺序早于这个值,此时Trace Span还未被创建,调用Tracer.getCurrentSpan()自然返回null。WebFlux环境的上下文特性
Micrometer Tracing在WebFlux(Reactor)环境中,Span是绑定在Reactor Context而非ThreadLocal中的。你当前直接在filter方法的主线程调用tracer.currentSpan(),此时Reactor Context还未与当前请求的Span绑定,无法获取到有效Span。
解决方案
步骤1:调整过滤器执行顺序
给自定义过滤器添加@Order注解,确保它在Trace过滤器之后执行:
@Component @RequiredArgsConstructor @Order(Ordered.HIGHEST_PRECEDENCE + 20) // 优先级低于TraceWebFilter public class GlobalFilterComponent implements GlobalFilter { // ... 原有代码 }
步骤2:正确从Reactor Context中获取Span
修改代码,在Reactor上下文绑定阶段获取Span,示例如下:
@Component @RequiredArgsConstructor @Order(Ordered.HIGHEST_PRECEDENCE + 20) public class GlobalFilterComponent implements GlobalFilter { private final Tracer tracer; @Override public Mono<Void> filter(final ServerWebExchange exchange, final GatewayFilterChain chain) { return chain.filter(exchange) .transformDeferredContextual((mono, contextView) -> { // 在Reactor上下文绑定后获取当前Span Optional<String> traceId = Optional.ofNullable(tracer.currentSpan()) .map(Span::context) .map(TraceContext::traceIdString); return mono.doFinally(signal -> { traceId.ifPresent(id -> exchange.getResponse().getHeaders().add("trace-id", id)); }); }); } }
或者用deferContextual简化实现:
@Override public Mono<Void> filter(final ServerWebExchange exchange, final GatewayFilterChain chain) { return chain.filter(exchange) .then(Mono.deferContextual(contextView -> { Span currentSpan = tracer.currentSpan(); Optional<String> traceId = Optional.ofNullable(currentSpan) .map(Span::context) .map(TraceContext::traceIdString); traceId.ifPresent(id -> exchange.getResponse().getHeaders().add("trace-id", id)); return Mono.empty(); })); }
额外检查
确认依赖完整性,确保引入以下核心依赖(以Maven为例):
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-tracing-bridge-brave</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
内容的提问来源于stack exchange,提问作者sge
相关产品推荐
相关产品推荐

