springboot在feign和线程池中使用TraceId日志链路追踪(最终版)-2

简述

书接前文:SpringBoot使用TraceId日志链路追踪-1

在上文中我们使用了springboot+MDC+Log4j2支持链路ID打印,但是如果我们使用feigin调用其他服务,线程池如何获取链路id呢;这里我们要用到阿里的TTL,在多线程面试中也会常用问到一个问题那就是线程传递问题。刚好这里就实践以下具体用法,并且这也是一个很好的案例。

问题

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

主要的难点是解决值传递问题,主要包括以下几个部分:
异步情况下(线程池)如何传递 MDC 中的 TraceId 到子线程
API Gateway 网关中如何传递 MDC 中的 TraceId
微服务之间互相远程调用时如何传递 MDC 中的 TraceId

阿里的TTL组件解决了线程池场景下的上下文传递问题。通过装饰线程池,TTL在任务提交时自动拷贝父线程的上下文到子线程,并在任务结束后清理副本,确保多级线程池调用链路完整。

feign调用时给head加入traceId

1.需要拦截feign的requst请求,并加入自定义的报文头信息
2.需要把这个拦截器配置到feign的配置项中

在application.yml配置文件里面,可以添加feign相关的配置信息,常见的配置信息有如下这些:

loggerLevel:日志级别,四个取值:

  • NONE 不打印日志;
  • BASIC:只打印请求方法、URL、响应状态码、执行时间。
  • HEADERS:打印请求头、响应头的日志信息。
  • FULL:打印所有日志。

连接配置参数

  • connectTimeout:连接超时时间,单位毫秒:ms。
  • readTimeout:读取超时时间,单位毫秒:ms。
  • retryer:重试策略。
  • requestInterceptors:自定义的拦截器,可以多个,是一个List集合。
  • defaultRequestHeaders:默认的请求头信息。
  • defaultQueryParameters:默认的查询参数信息。
  • followRedirects: 是否允许重定向。

这里我们开启HEADERS级别的日志,方便本地服务调用时打印报文头我们可以查看是否TraceId信息;


import feign.RequestInterceptor;
import feign.RequestTemplate;
import gyqx.spd.common.constants.GlobalConstants;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.jboss.logging.MDC;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Optional;

/**
 * @version 1.0.0
 * @Date: 2025/3/15 8:49
 * @Description: 自定义feigin请求拦截器加入traceId,甚至我们可以把前端携带的token信息和用户id等报文头也放进来,方便转发给下一个被调用的服务
 */
@Slf4j
public class CustomFeignInterceptor implements RequestInterceptor {
   
   


    @Override
    public void apply(RequestTemplate template) {
   
   
        // TODO 在这里可以实现一些自定义的逻辑,例如:用户认证
        log.info("Feign执行拦截器....");
        Optional.ofNullable(RequestContextHolder.getRequestAttributes()).map(it -> ((ServletRequestAttributes) it).getRequest())
                .ifPresent(it -> {
   
   
                            String traceId = it.getHeader(GlobalConstants.GLOBAL_X_TRACE_ID);

                            if (StringUtil.isEmpty(traceId)) {
   
   
                                traceId = MDC.get(GlobalConstants.GLOBAL_X_TRACE_ID) == null ? null : MDC.get(GlobalConstants.GLOBAL_X_TRACE_ID).toString();
                            }

                            if (StringUtil.isNotBlank(traceId)) {
   
   
                                MDC.put(GlobalConstants.GLOBAL_X_TRACE_ID, traceId);
                                template.header(GlobalConstants.GLOBAL_X_TRACE_ID, traceId);
                            }
                            log.info("Feign执行拦截器traceId={}", traceId);
                        }
                );

    }
}

FeignConfig配置

一般都是全局配置,每个服务引入依赖自动配置生效,当然如果只测试可以在某个feigin上自己加上


import feign.RequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.C
<think>首先,用户的问题是关于在Spring Boot 3中使用micrometer-tracing-bridge-brave实现链路追踪日志收集的方法。我需要基于提供的站内引用来回答。 回顾引用内容: - 引用[1]: 介绍了Micrometer Tracing、Zipkin、Brave等组件,以及相关依赖如micrometer-observation、micrometer-tracing-bridge-brave、zipkin-reporter-brave、spring-boot-starter-actuator、feign-micrometer。简要说明了Brave的功能。 - 引用[2]: 描述了Micrometer Tracing是基于Micrometer的分布式追踪解决方案,集成了Zipkin或Jaeger,用于追踪请求。 - 引用[3]: 解释了链路追踪的概念,如Trace IDSpan ID,以及Zipkin的作用。 用户的问题具体是:在Spring Boot 3中使用micrometer-tracing-bridge-brave实现链路追踪日志收集的方法。 我的回答需要: - 使用中文。 - 结构清晰,逐步解决问题。 - 参考提供的引用。 - 在引用的段落末尾自然地添加引用标识,例如[^1]。 - 生成相关问题。 - 对于数学表达式,使用正确的LaTeX格式(但在这个主题中,可能没有数学表达式,所以我可以忽略)。 - 确保回答真实可靠。 关键点: - 用户指定了Spring Boot 3。 - 使用micrometer-tracing-bridge-brave。 - 实现链路追踪日志收集。 我需要构建一个结构化的回答: 1. **引言**: 简要解释什么是链路追踪Spring Boot中的重要性。 2. **依赖设置**: 描述如何添加必要的依赖,特别是针对Spring Boot 3。 3. **配置**: 如何配置Micrometer Tracing、BraveZipkin。 4. **日志收集**: 如何集成日志收集(例如,使用SLF4JMDC)。 5. **示例代码**: 提供代码片段来展示实现。 6. **验证**: 如何测试验证追踪。 7. **引用**: 自然地引用提供的内容。 8. **相关问题**: 在最后生成相关问题。 从引用中提取相关信息: - 引用[1]: 提到了依赖,如micrometer-tracing-bridge-bravezipkin-reporter-brave。 - 引用[2]: 描述了Micrometer Tracing的功能。 - 引用[3]: 解释了Trace IDSpan ID。 对于Spring Boot 3,我需要确保依赖是兼容的。Spring Boot 3使用Spring Framework 6,可能对依赖版本有要求。我应该建议使用最新稳定版。 **步骤实现链路追踪**: 1. 添加依赖到pom.xml(如果使用Maven)。 2. 配置application.properties或application.yml。 3. 确保日志记录集成Trace ID(使用MDC)。 4. 发送追踪数据到Zipkin或其他后端。 **日志收集**: 链路追踪通常包括Trace ID在日志中,以便关联日志追踪。这可以通过配置日志框架(如Logback或Log4j2)来输出MDC中的Trace ID。 生成相关问题: - 类似于示例,例如: 1. 如何优化Micrometer Tracing的性能? 2. Micrometer Tracing与其他工具的比较? 3. 如何处理追踪数据的安全性? 确保回答中自然地添加引用: - 当提到Brave时,引用[^1]。 - 当提到Micrometer Tracing时,引用[^2]。 - 当提到Trace IDSpan ID时,引用[^3]。 现在,起草回答结构: - **开头**: 解释链路追踪的重要性。 - **添加依赖**: 列出必要的依赖。 - **配置**: 设置Zipkin报告器日志- **示例**: 提供简单的代码示例。 - **日志收集**: 描述如何集成日志- **结尾**: 总结并生成相关问题。 </think>### Spring Boot 3中使用micrometer-tracing-bridge-brave实现链路追踪日志收集的方法 在Spring Boot 3中,通过集成Micrometer TracingBrave,可以实现分布式链路追踪日志收集。这有助于监控请求在微服务架构中的流转路径性能问题。Brave是一个开源的分布式跟踪工具,它使用“跟踪上下文”机制在请求头中存储Trace IDSpan ID,确保请求链的可追踪性[^1]。Micrometer Tracing则基于Micrometer指标库,提供与Zipkin等系统的集成支持,用于收集报告追踪数据[^2]。一条完整的链路追踪会在每个服务调用时添加Trace ID(唯一标识请求链)Span ID(标识每个请求步骤), 各Span通过parent ID关联起来[^3]。以下我将逐步介绍实现方法,确保依赖、配置代码正确。 #### 步骤1: 添加必要依赖 在Spring Boot 3项目中,需添加Micrometer Tracing、BraveZipkin的依赖。Spring Boot 3默认支持Micrometer集成,因此使用Spring Boot Starter简化配置。在Maven的`pom.xml`中添加以下依赖(确保版本兼容Spring Boot 3,如使用Spring Boot 3.2.x或更高): ```xml <dependencies> <!-- Spring Boot Actuator for monitoring --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Micrometer Tracing with Brave bridge --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-tracing-bridge-brave</artifactId> <version>1.2.0</version> <!-- 推荐使用最新版本 --> </dependency> <!-- Zipkin reporter for Brave --> <dependency> <groupId>io.zipkin.reporter2</groupId> <artifactId>zipkin-reporter-brave</artifactId> <version>2.17.0</version> </dependency> <!-- Optional: For HTTP client tracing (e.g., WebClient or Feign) --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-micrometer</artifactId> <version>12.5</version> </dependency> <!-- Ensure logging integration (e.g., Logback) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> ``` 这些依赖包括: - `micrometer-tracing-bridge-brave`: 作为Brave的桥梁,收集分布式跟踪数据[^1]。 - `zipkin-reporter-brave`: 将Brave数据报告到Zipkin后端[^1]。 - `spring-boot-starter-actuator`: 提供监控端点,暴露追踪指标[^1]。 - `feign-micrometer`: 可选,用于HTTP客户端追踪。 #### 步骤2: 配置应用属性 在`application.properties`或`application.yml`中配置Zipkin报告器日志设置。Spring Boot 3自动检测这些配置,简化集成: ```properties # 启用Zipkin报告器 management.tracing.enabled=true management.zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans # Zipkin服务器地址(默认本地9411端口) management.tracing.sampling.probability=1.0 # 采样率,1.0表示收集所有请求 # 配置日志输出Trace ID(日志收集关键) logging.pattern.level=%5p [${spring.application.name:-},%X{traceId:-},%X{spanId:-}] # 在日志中添加Trace IDSpan ID management.endpoints.web.exposure.include=health,metrics,trace # 暴露Actuator端点 ``` - **链路追踪配置**: 启用追踪并指向Zipkin服务器。Brave会自动处理请求头中的Trace IDSpan ID传递[^3]。 - **日志收集配置**: 使用`logging.pattern.level`集成MDC(Mapped Diagnostic Context),将Trace ID注入日志格式。这样每条日志都会包含Trace ID,便于在日志系统(如ELK或Splunk)中关联追踪数据[^2]。 #### 步骤3: 实现服务端追踪Spring Boot应用中,使用`@RestController`或服务类时,Brave会自动拦截请求添加追踪上下文。例如,创建一个简单控制器: ```java import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import io.micrometer.tracing.Tracer; // 导入Tracer接口 @RestController public class TraceController { private final Tracer tracer; // 注入Tracer Bean public TraceController(Tracer tracer) { this.tracer = tracer; } @GetMapping("/trace") public String traceEndpoint() { // 手动添加Span(可选,Brave默认自动处理) Span span = tracer.nextSpan().name("custom-span").start(); try (var ignored = tracer.withSpan(span)) { // 模拟服务逻辑 return "Trace ID: " + tracer.currentSpan().context().traceId(); // 输出当前Trace ID } finally { span.end(); // 结束Span } } } ``` - **自动追踪**: Spring Boot 3的AOP机制会自动为HTTP请求创建Span。使用`Tracer` Bean(由`micrometer-tracing-bridge-brave`提供)可以手动管理Span[^1]。 - **日志集成**: 在日志文件中,Trace ID会像`INFO [app-name,1234567890abcdef,56789]`一样输出,便于查询关联。 #### 步骤4: 配置日志收集与Zipkin可视化 - **日志收集**: 确保日志框架(如Logback)输出到文件或集中式系统(如ELK Stack)。在`logback-spring.xml`中添加配置: ```xml <configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>logs/application.log</file> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - [TraceID: %X{traceId}, SpanID: %X{spanId}] %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="FILE" /> </root> </configuration> ``` 这强制每条日志包含Trace IDSpan ID,实现日志追踪的关联[^3]。 - **Zipkin可视化**: 启动Zipkin服务(如Docker容器): ```bash docker run -d -p 9411:9411 openzipkin/zipkin ``` 访问`http://localhost:9411`查看追踪数据。请求通过Brave报告到Zipkin后,Zipkin会展示请求路径、耗时日志关联[^1]。 #### 步骤5: 测试验证 1. **启动应用**: 运行Spring Boot 3应用,访问`http://localhost:8080/trace`触发请求。 2. **检查日志**: 在`application.log`中查看Trace ID,如`2024-10-01 12:00:00 INFO [http-nio-8080-exec-1] - [TraceID: 123456, SpanID: 7890] Endpoint called`。 3. **Zipkin验证**: 在Zipkin UI中搜索Trace ID,确认请求链可视化(包括服务Span详情)。 4. **Actuator端点**: 访问`http://localhost:8080/actuator/trace`查看本地追踪数据[^1]。 #### 注意事项 - **性能影响**: 采样率`management.tracing.sampling.probability`设为1.0可能增加负载,生产环境可调整为0.1[^2]。 - **安全性**: 确保Zipkin端点安全(如使用Spring Security)。 - **兼容性**: Spring Boot 3与Micrometer Tracing 1.x完全兼容,避免版本冲突。 通过以上方法,您可以在Spring Boot 3中高效实现链路追踪日志收集。Brave处理追踪上下文,Zipkin提供可视化,Micrometer Tracing桥接两者并集成日志[^1][^2][^3]。如有问题,可以从Actuator端点排查追踪数据。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值