Spring Boot3迁移后traceId跨HTTP/Kinesis传播配置问题
问题背景
从Spring Boot 2.7.7/Spring Cloud 2021.0.5迁移到Spring Boot 3.0.1/Spring Cloud 2022.0.0,改用io.micrometer:micrometer-tracing-bridge-otel后,出现traceId无法跨HTTP REST、Kinesis消息边界传播的问题——不同微服务的日志里traceId不统一。旧版本中HTTP无需额外配置,Kinesis只要加b3 header就能实现传播,新版本迁移指南提到默认不支持joined spans,对这个配置的可选性以及默认关闭的原因存在困惑。
最小配置方案
1. HTTP REST 链路传播修复
如果自定义声明了RestTemplateBuilder Bean,会覆盖Spring Boot自动配置的trace拦截器,直接导致traceId传播失效。
- 最简方案:移除自定义的
RestTemplateBuilderBean,Spring Boot会自动生成带trace传播能力的RestTemplate。 - 若必须自定义RestTemplate,手动添加trace拦截器:
@Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder.additionalInterceptors(new ObservationClientHttpRequestInterceptor()) .build(); }
2. Kinesis 链路传播配置
无需全局ChannelInterceptor,通过配置NewDestinationBindingCallback Bean,在消息绑定阶段注入traceparent header即可:
@Bean public NewDestinationBindingCallback kinesisTracingBindingCallback(Tracer tracer) { return (destination, channel, message) -> { Span currentSpan = tracer.currentSpan(); if (currentSpan != null) { String traceparent = W3CTraceContext.encode(currentSpan.context()); message.getHeaders().put("traceparent", traceparent); } }; }
消费者端无需额外配置,Spring Cloud Stream的Kinesis binder默认会解析traceparent header关联traceId。
关于Joined Spans的说明
新版本默认不启用joined spans,是因为Micrometer Tracing默认采用分离span模式——每个服务/组件生成独立span,仅通过traceId关联,这是OpenTelemetry的推荐链路追踪模式。如果需要还原旧版的joined spans(父子span合并),可以通过配置开启:
micrometer.tracing.join.enabled=true
排查过程记录
- HTTP传播失效排查:定位到自定义
RestTemplateBuilder覆盖了自动配置的trace拦截器,移除后traceId跨服务传播恢复正常; - Kinesis传播尝试:最初尝试自定义
ChannelInterceptor设置traceparentheader,但消费者未正确解析,原因是Spring Cloud Stream的Kinesis binder对消息头的处理逻辑特殊; - 最终解决方案:改用
NewDestinationBindingCallback在消息绑定阶段注入trace上下文,适配Kinesis binder的处理流程,成功实现traceId跨生产者/消费者传播。
内容的提问来源于stack exchange,提问作者Keith Bennett

