You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Spring Cloud Sleuth切换到Micrometer后,Spring Cloud Gateway中Tracer.getCurrentSpan()为何失效?

问题原因及解决方案

核心原因

  1. 过滤器执行顺序过早
    Spring Cloud Gateway中负责初始化Trace Span的TraceWebFilter默认优先级为Ordered.HIGHEST_PRECEDENCE + 10,如果你的自定义全局过滤器执行顺序早于这个值,此时Trace Span还未被创建,调用Tracer.getCurrentSpan()自然返回null。

  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 03:52:48