夏有木工作室夏有木工作室夏有木工作室
  • 首页
  • 博客
  • 关于我们
  • 联系我们
夏有木工作室夏有木工作室夏有木工作室
全部文章/
架构设计

分布式追踪:SpringBoot 3.x + MDC

EricEric
2024/08/15
·3 分钟阅读 (712 字)·

基于 Spring Boot 3.x 与 Logback MDC,实现微服务全链路 TraceId 自动生成、跨线程传递与排障全景日志追踪。

目录

  • 问题
  • 环境准备
  • 01 API Gateway 网关
  • 02 下游微服务拦截 Http Header
  • 03 下游微服务互相调用
  • 04 异步多线程传递问题
  • 改造 LogbackMDCAdapter
  • 替换 Spring 默认线程池
  • 小结
  • 附录
  • 架构设计推荐阅读

如果不想引入第三方组件,比如:Sping Cloud Sleuth ,可以采用轻量级的解决方案来完成分布式系统下的日志链路追踪。

同时本文主要聚焦在日志的链路追踪,服务之间的调用链路追踪,可采用工具实现,比如:Jaeger、Zipkin、SkyWalking、Pinpoint、Elastic APM 等。

问题

Spring 默认的日志框架 Logback 中提供的 LogbackMDCAdapter 内部使用的是ThreadLocal,只有本线程才有效,子线程和下游的服务 MDC 里的值会丢失。

主要的难点是解决值传递问题,主要包括以下几个部分:

  • API Gateway 网关中如何传递 MDC 中的 TraceId
  • 微服务之间互相远程调用时如何传递 MDC 中的 TraceId
  • 异步情况下(线程池)如何传递 MDC 中的 TraceId 到子线程
  • ........

环境准备

- Java 21
- Spring Boot 3.2.4
- Spring Cloud 2023.0.1
- Spring Cloud Gateway 4.1.2
- Spring Cloud OpenFeign 4.1.1
- Alibaba Transmittable Thread Local 2.14.5

如何搭建微服务框架代码不再这里赘述。

01 API Gateway 网关

创建一个GlobalTraceFilter 进行 Web 请求 和 路由请求的 TraceId 过滤处理,参考:

image-20240731151029599

配置 Logback 文件 logback-spring.xml:

image-20240812185339647

<springProperty scope="context" name="appName" source="spring.application.name"/>
<property name="CONSOLE_LOG_PATTERN" value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%level){blue} %clr(${PID}){magenta} %clr([%X{traceId:-}]){yellow} %clr([${appName}]){blue} %clr([%thread]){orange} %clr(%-40.40logger{39}){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>

02 下游微服务拦截 Http Header

解析 Http 请求 Header 中的 TraceId,可以看到由第一步 Api Gateway 设置的。创建一个

image-20240730225438710

03 下游微服务互相调用

创建 OpenFeign Interceptor ,下游服务之间的相互调用统一使用 FeignClient 进行调用。

image-20240730225658064

04 异步多线程传递问题

改造 LogbackMDCAdapter

新建一个 MDCAdapter 使用阿里巴巴的 TransmittableThreadLocal 替换 LogbackMDCAdapter中 ThreadLocal,来解决多线程无法传递 MDC 值问题。

SpringBoot 3.0 以上版本后,无法替换 Logback 的 MDC Adapter,需要将我们新建的 MDC Adapter配置到spi文件,参考下图 META-INFO下services 目录中的SLF4JServiceProvider。

image-20240730232149611

成功后日志输出如下:

image-20240730233220561

但是每次启动都会有类似的错误提醒,后续看下是否可以优化。

替换 Spring 默认线程池

同理也是使用 alibaba 的 TtlRunnable进行替换。

image-20240730231425509

小结

随着系统管理的服务数量的不断增加,了解系统在生产环境的状态愈发困难,同时也导致排查问题故障变得更加困难,建议在考虑采用微服务架构之前,将日志聚合和分布式追踪作为先决条件。

附录

Gateway 改造 MDC 后验证:

image-20240730232650310

image-20240731112953661

下游服务调用:

1)通过 Gateway 请求下游服务

image-20240731121106635

image-20240731151439130

2)下游服务日志查看 TraceId

image-20240731151723641

可观测性(Elastic Stack ):

关于如何部署可视化工具,参考公众号之前 Elastic 可观测性系列文章。

image-20240731193340535

CI/CD 管道的屏幕截图

Spring Cloud Sleuth:

Trace Info propagation

架构设计推荐阅读

如果你对高并发 API 性能优化、分布式数据一致性、索引治理与系统稳定性感兴趣,推荐阅读:

  • 数据一致性方案设计
  • API 接口性能优化
  • MySQL 创建高性能的索引
  • 异步批处理方案设计:JDK21 + 虚拟线程
  • 分布式追踪:SpringBoot 3.x + MDC
  • 良好的异常处理设计:系统稳定性的基础保障

👉 查阅更多企业级系统设计与工程实战,欢迎访问 架构设计专栏完整目录。

上一篇

DDD 分层架构落地实践

下一篇

异步批处理方案设计:JDK21 + 虚拟线程

更多文章

使用 Sa-Token 平替 Spring Security,告别繁琐的认证与鉴权

使用 Sa-Token 平替 Spring Security,告别繁琐的认证与鉴权

对比传统 Spring Security 的复杂繁重,分享使用轻量 Sa-Token 框架实现无痛多端鉴权、单点登录与路由拦截的最佳实践。

EricEric
2025/01/15
为什么写不好 DDD 代码?

为什么写不好 DDD 代码?

深度剖析为什么大部分团队写不好 DDD,从建模思维、业务边界侵蚀到防腐层设计,解析领域驱动的核心痛点与破局解法。

EricEric
2025/01/14
良好的异常处理设计:系统稳定性的基础保障

良好的异常处理设计:系统稳定性的基础保障

探讨企业级后端的全局异常体系设计,规范业务错误码、状态流转异常捕获与微服务防御性兜底保障。

EricEric
2024/11/27
夏有木工作室夏有木工作室夏有木工作室

专业软件开发技术伙伴,帮助客户快速构建出高质量的软件产品。

GitHubGitHubEmail
Built with夏有木工作室夏有木工作室夏有木

川公网安备51012202002478号|蜀ICP备2025156031号-1

产品
  • 夏有木进销存
工具
  • 夏有木微信公众号排版
资源
  • 博客
  • 更新日志
公司
  • 关于我们
  • 联系我们
法律
  • Cookie政策
  • 隐私政策
  • 服务条款
© 2026 夏有木工作室 All Rights Reserved.