不存在“provides with模式”,分布式追踪中traceId传递依赖入口注入、跨服务透传和跨线程延续三类动作,需通过MDC、HTTP头及TransmittableThreadLocal等机制实现。

“provides with 模式”并不是 Java 或 Spring 生态中标准术语,当前主流框架(Spring Boot、SLF4J、Logback)及分布式追踪实践(如 SkyWalking、OpenTelemetry)中均无官方定义的 provides with 模式。你提到的表述,极可能是对某种配置写法、依赖注入风格或文档翻译偏差的误记——比如混淆了 Spring 的 @Bean 方法签名中的 provides(常见于 Kotlin DSL 或某些构建工具描述),或误将 “propagates with”(即“携带传递”)听/读作 “provides with”。
真正起作用的是 traceId 的跨模块“传递机制”,不是“provides with”
在分布式日志追踪中,MDC 中的 traceId 要贯穿网关、服务、Feign 调用、线程池子线程等场景,靠的是明确的三类传递动作:
-
入口注入:在请求最开始(如网关 Filter 或 Spring WebMvc HandlerInterceptor)生成
traceId,并调用MDC.put("traceId", id) -
跨服务透传:通过 HTTP Header(如
X-Trace-ID)将 ID 发送给下游;下游收到后再次MDC.put绑定到当前线程 -
跨线程延续:主线程的 MDC 内容默认不会进入线程池子线程(因 ThreadLocal 隔离)。必须借助
TransmittableThreadLocal+TtlRunnable/TtlCallable包装任务,或使用已集成 TTL 的线程池(如TtlExecutors.getTtlExecutorService)
各模块如何协作完成 traceId 传递
无需虚构“provides with”,只需按职责分层实现:
-
网关模块:添加
OncePerRequestFilter,生成 UUID 作为traceId,写入MDC,同时塞进HttpServletResponseheader 向下游转发 -
业务服务模块:
- 注册
HandlerInterceptor接收 header 中的X-Trace-ID,存入MDC - 配置
FeignClient的RequestInterceptor,自动从当前MDC取traceId并设为请求头
- 注册
-
异步模块(@Async / 线程池):
- 替换默认
MDCAdapter为TtlMDCAdapter(继承自ch.qos.logback.classic.util.LogbackMDCAdapter) - 所有提交到线程池的任务,必须用
TtlRunnable.get(runnable)包装;若用@Async,需自定义AsyncConfigurer返回基于 TTL 的ThreadPoolTaskExecutor
- 替换默认
关键配置示例(Logback + TTL)
确保日志格式含 traceId:
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level [%X{traceId}] %logger{36} - %msg%n</pattern>并在启动类或配置类中指定 MDC Adapter:
System.setProperty("logback.mdc.adapter", "com.example.TtlMDCAdapter");其中 TtlMDCAdapter 内部使用 TransmittableThreadLocal<Map<String, String>> 替代原生 ThreadLocal,使 map 可跨线程继承。
不依赖“模式”,依赖契约与包装
所谓“跨模块传递”,本质是各模块遵守同一契约:
→ 入口统一注入
→ 远程调用统一透传 header
→ 异步执行统一包装任务
没有魔法模式,只有清晰的责任划分和必要的适配封装。

















