文章

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

image-20240730190414419

如果不想引入第三方组件,比如: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

License:  CC BY 4.0