WebFlux WebFilter中Sleuth tracer.currentSpan()为空 如何添加Trace ID到响应头
问题根因
WebFlux是异步响应式架构,Sleuth 3.x的链路上下文默认绑定在Reactor的Context中,而非传统的ThreadLocal。你代码里的response.beforeCommit回调是在独立的异步线程执行,脱离了原有链路的Reactor上下文,直接调用tracer.currentSpan()只能从当前线程的ThreadLocal读取数据,自然会拿到null。
修复方案
方案1:提前从Reactor上下文获取Span信息
通过Mono.deferContextual拿到当前请求的Reactor上下文,提前读取Span存入回调的闭包中,避免在beforeCommit里再读取上下文:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.sleuth.Span; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; @Component @Order(Ordered.HIGHEST_PRECEDENCE + 6) public class GatewaySleuthFilter implements WebFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { return Mono.deferContextual(contextView -> { // 从Reactor上下文读取Sleuth存入的Span if (contextView.hasKey(Span.class)) { Span span = contextView.get(Span.class); exchange.getResponse().beforeCommit(() -> { exchange.getResponse().getHeaders().add("trace-id", span.context().traceId()); exchange.getResponse().getHeaders().add("span-id", span.context().spanId()); return Mono.empty(); }); } return chain.filter(exchange); }); } }
方案2:配置Filter执行顺序
Sleuth自带的TraceWebFilter默认优先级是HIGHEST_PRECEDENCE + 5,给自定义Filter设置@Order(Ordered.HIGHEST_PRECEDENCE + 6),保证你的Filter在Sleuth链路上下文初始化完成之后再执行,避免拿不到Span。
注意事项
- 不要修改Sleuth默认的响应式上下文配置,
spring.sleuth.reactor.enabled默认值为true,不需要手动调整 - 检查项目配置,确认没有关闭Sleuth的WebFlux自动配置,排除
spring.sleuth.web.enabled=false这类配置项
内容的提问来源于stack exchange,提问作者Julie
相关产品推荐
相关产品推荐

