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

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

问题原因

  1. getValue()方法设计逻辑:BaggageField.getValue()默认不会自动关联当前活跃的Trace上下文,必须显式传入SpanContext才能获取绑定的值。
  2. Span上下文缺失:如果当前线程没有活跃的Span(Sleuth未正确追踪请求),updateValue()无法将值绑定到有效上下文,后续自然获取不到结果。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:40:28