Spring Cloud Sleuth中更新BaggageField后getValue()返回null问题排查
Spring Cloud Sleuth BaggageField更新后getValue返回null问题排查
问题重现
配置文件(application.yml)
sleuth: baggage: remote-fields: userId correlation-fields: userId
自定义配置类
@Configuration public class SleuthConfiguration { @Bean public BaggageField userIdBaggageField() { return BaggageField.create("userId"); } @Bean public CurrentTraceContext.ScopeDecorator mdcScopeDecorator() { return MDCScopeDecorator.newBuilder() .clear() .add(CorrelationScopeConfig.SingleCorrelationField .newBuilder(userIdBaggageField()) .flushOnUpdate() .build()) .build(); } }
控制器代码
@RestController @Slf4j static class SampleController { private final BaggageField userIdBaggageField; SampleController(BaggageField userIdBaggageField) { this.userIdBaggageField = userIdBaggageField; } @GetMapping("/sample") public void periodes(@RequestParam String userId) { log.info("Setting BaggageField to {}", userId); this.userIdBaggageField.updateValue(userId); log.info("BaggageField value {}", this.userIdBaggageField.getValue()); } }
日志输出
Setting BaggageField to 1234 BaggageField value null
问题原因
getValue()方法设计逻辑:BaggageField.getValue()默认不会自动关联当前活跃的Trace上下文,必须显式传入SpanContext才能获取绑定的值。- Span上下文缺失:如果当前线程没有活跃的Span(Sleuth未正确追踪请求),
updateValue()无法将值绑定到有效上下文,后续自然获取不到结果。 flushOnUpdate作用局限:该配置仅负责将Baggage值同步到MDC,不影响getValue()的获取逻辑。
解决方案
1. 确保Sleuth追踪正常生效
确认项目已引入spring-cloud-starter-sleuth依赖,且未禁用Sleuth自动配置(无spring.sleuth.enabled=false配置)。可通过查看请求日志中的TraceID/SpanID,验证追踪是否正常启动。
2. 正确获取Baggage值
不要直接调用无参的getValue(),而是通过当前Span上下文获取:
@RestController @Slf4j static class SampleController { private final BaggageField userIdBaggageField; private final Tracer tracer; SampleController(BaggageField userIdBaggageField, Tracer tracer) { this.userIdBaggageField = userIdBaggageField; this.tracer = tracer; } @GetMapping("/sample") public void periodes(@RequestParam String userId) { log.info("Setting BaggageField to {}", userId); this.userIdBaggageField.updateValue(userId); // 方式1:通过Tracer获取当前SpanContext并取值 String value1 = tracer.currentSpan().context().getBaggageItem(userIdBaggageField.name()); // 方式2:通过BaggageField的带参get方法取值 String value2 = userIdBaggageField.get(tracer.currentSpan().context()); log.info("BaggageField value (方式1): {}", value1); log.info("BaggageField value (方式2): {}", value2); } }
3. 简化配置(可选)
如果仅需要实现Baggage跨服务传递和MDC同步,可删除自定义配置类,直接通过配置文件完成:
sleuth: baggage: remote-fields: userId # 跨服务传递的Baggage字段 correlation-fields: userId # 关联到MDC的字段 mdcs: userId # 自动将Baggage同步到MDC
Sleuth会自动创建对应的BaggageField实例并处理MDC同步,无需手动编写配置类。
4. 验证Span上下文存在
在调用updateValue()前,打印当前Span确认是否存在:
log.info("Current Span: {}", tracer.currentSpan());
如果输出为null,说明请求未被Sleuth追踪,需排查依赖引入、自动配置是否正常。
内容的提问来源于stack exchange,提问作者Florian Lopes
相关产品推荐
相关产品推荐

