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

Spring Cloud Sleuth请求头缺失时如何初始化Baggage项

WebFlux 环境下 Baggage 字段缺省自动生成的最佳实现

你现有配置已经完成了x-fapi-interaction-id的跨服务传播注册,只需要补充入口请求的缺省值生成逻辑即可,核心要求是生成逻辑必须在链路上下文初始化完成前执行,避免出现Baggage写入过晚导致异步线程、子Span、下游服务拿不到值的问题。

实现步骤

  1. 保留你原有两个Baggage传播相关的Bean配置,不需要改动
  2. 新增ObservationFilter组件(适配Spring Boot 2.7+ / 3.x 内置的Micrometer Tracing链路体系,也是WebFlux环境下最稳妥的实现方式),在HTTP入口请求的根Span刚创建时就检查字段值,缺失则自动生成。

完整配置代码

@Configuration
public class FAPIAutoConfiguration {

    private static final String INTERACTION_ID = "x-fapi-interaction-id";
    private final BaggageField fapiBaggageField = BaggageField.create(INTERACTION_ID);

    @Bean
    BaggagePropagationCustomizer baggagePropagationCustomizer() {
        return builder -> builder.add(SingleBaggageField.remote(fapiBaggageField));
    }

    @Bean
    CorrelationScopeCustomizer correlationScopeCustomizer() {
        return builder -> builder.add(SingleCorrelationField.create(fapiBaggageField));
    }

    @Bean
    ObservationFilter fapiInteractionIdGenerator(Tracer tracer) {
        return context -> {
            // 仅拦截服务端HTTP入口请求,避免内部调用、客户端请求场景重复生成ID
            if (context instanceof ServerRequestObservationContext serverCtx) {
                // 优先从已初始化的Baggage取值,不存在则直接从请求头读取
                String interactionId = tracer.getBaggage(INTERACTION_ID).get();
                if (interactionId == null || interactionId.isBlank()) {
                    interactionId = serverCtx.getCarrier().getFirst(INTERACTION_ID);
                }
                // 两处都取不到值时,自动生成符合FAPI规范的UUID作为交互ID
                if (interactionId == null || interactionId.isBlank()) {
                    interactionId = UUID.randomUUID().toString();
                    // 写入Baggage并绑定到当前作用域,自动透传给所有子Span、异步线程、下游服务
                    try (BaggageInScope ignored = tracer.createBaggageInScope(INTERACTION_ID, interactionId)) {
                        // 按FAPI规范要求,将ID写入响应头返回给调用方
                        serverCtx.getResponse().addHeader(INTERACTION_ID, interactionId);
                    }
                }
            }
            return context;
        };
    }
}

注意事项

  • 别用普通WebFilter实现生成逻辑:普通WebFilter默认执行顺序在链路追踪核心过滤器之后,此时根Span、MDC上下文已经初始化完,再写Baggage会出现入口日志打不上ID、异步线程拿不到值的问题。ObservationFilter是在观测上下文刚创建的时候执行,写进去的Baggage会自动带到所有子Span、异步线程、下游请求里,不会丢。
  • 生成ID直接用标准UUID字符串就行,完全符合FAPI协议对x-fapi-interaction-id的格式要求。
  • 上面的实现自动兼容两种场景:请求头带了ID就直接透传,没带就自己生成,两种情况都会把ID写回响应头,符合FAPI的规范要求。
  • 如果你用的是Spring Cloud 2020之前的旧版Sleuth,没有内置Micrometer Tracing,把ObservationFilter换成自定义WebFilter就行,执行顺序设成Ordered.HIGHEST_PRECEDENCE + 10(比链路核心过滤器优先级低10位,保证上下文已经创建但还没开始向后传播),里面取值、生成、写Baggage的逻辑和上面完全一样。

内容的提问来源于stack exchange,提问作者Víctor Herraiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:06:20