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

Spring Cloud Gateway GlobalFilter中无法获取Trace ID(Brave+Zipkin)

问题:Spring Cloud Gateway后置过滤器中TraceContext为null,无法添加Trace ID到响应头

我编写了一个后置过滤器,尝试将Trace ID添加到响应头中,按相关方法操作后,TraceContext始终为null。

过滤器代码

@Slf4j
@Configuration
public class PostFilters {

    public static final String CORRELATION_ID = "X-CORRELATION-ID";

    @Bean
    public GlobalFilter correlationIdPostFilter() {
        return(exchange, chain) -> chain.filter(exchange)
            .then(Mono.just(exchange))
            .map(serverWebExchange ->  {
                TraceContext traceContext = WebFluxSleuthOperators.currentTraceContext(serverWebExchange);
                log.info("Trace Context: {}", traceContext);
                if (traceContext != null) {
                    serverWebExchange.getResponse().getHeaders().set(CORRELATION_ID, traceContext.traceId());
                }
                return serverWebExchange;
            })
            .then();
    }
}

依赖配置

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-tracing-bridge-brave</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.reporter2</groupId>
            <artifactId>zipkin-reporter-brave</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.reporter2</groupId>
            <artifactId>zipkin-sender-okhttp3</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-sleuth-instrumentation</artifactId>
        </dependency>

主类代码

@SpringBootApplication
public class ApiGatewayApplication {

    public static void main(String[] args) {
        Hooks.enableAutomaticContextPropagation();
        new SpringApplicationBuilder(ApiGatewayApplication.class)
                .web(WebApplicationType.REACTIVE)
                .run(args);
    }
}

已确认上下文传播正常,日志和Zipkin中能看到跨服务的Trace ID。


解决方案

问题根源

chain.filter(exchange)执行完成后,Trace上下文已被清理,后续通过WebFluxSleuthOperators.currentTraceContext无法获取到有效上下文。

修复方案一:在请求处理回调中直接处理

使用doOnSuccess替代then(Mono.just(exchange)),确保在上下文未被清理时操作响应头:

@Slf4j
@Configuration
public class PostFilters {

    public static final String CORRELATION_ID = "X-CORRELATION-ID";

    @Bean
    public GlobalFilter correlationIdPostFilter() {
        return (exchange, chain) -> chain.filter(exchange)
                .doOnSuccess(aVoid -> {
                    TraceContext traceContext = WebFluxSleuthOperators.currentTraceContext(exchange);
                    log.info("Trace Context: {}", traceContext);
                    if (traceContext != null) {
                        exchange.getResponse().getHeaders().set(CORRELATION_ID, traceContext.traceId());
                    }
                });
    }
}

修复方案二:提前保存Trace ID

在过滤器前置阶段获取Trace ID并存储到Exchange属性中,后置阶段直接取用:

@Slf4j
@Configuration
public class PostFilters {

    public static final String CORRELATION_ID = "X-CORRELATION-ID";
    private static final String TRACE_ID_ATTR = "TRACE_ID_ATTR";

    @Bean
    public GlobalFilter correlationIdPostFilter() {
        return (exchange, chain) -> {
            // 前置阶段保存Trace ID
            TraceContext traceContext = WebFluxSleuthOperators.currentTraceContext(exchange);
            if (traceContext != null) {
                exchange.getAttributes().put(TRACE_ID_ATTR, traceContext.traceId());
            }
            return chain.filter(exchange)
                    .doOnSuccess(aVoid -> {
                        // 后置阶段取出Trace ID设置响应头
                        String traceId = exchange.getAttribute(TRACE_ID_ATTR);
                        if (traceId != null) {
                            exchange.getResponse().getHeaders().set(CORRELATION_ID, traceId);
                        }
                    });
        };
    }
}

额外优化建议

如果使用Spring Cloud 2023.0.x及以上版本,可直接注入Tracer bean获取上下文:

@Autowired
private Tracer tracer;

// 在处理逻辑中调用
TraceContext traceContext = tracer.currentTraceContext().context();

内容的提问来源于stack exchange,提问作者Jacob L

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 03:15:01