当前位置: 首页 > news >正文

TraceId如何在Spring-Cloud微服务的REST调用中传递

文章目录

      • 推荐方案:基于Spring Cloud Sleuth(无侵入,官方推荐)
        • 1. 集成Sleuth
        • 2. 核心原理
        • 3. 日志配置(输出traceId)
        • 4. 验证
      • 自定义实现方案(不依赖Sleuth,了解原理)
        • 1. 定义常量(统一Header键)
        • 2. 发送端:通过拦截器传递traceId
          • (1)RestTemplate调用场景
          • (2)Feign调用场景
        • 3. 接收端:通过过滤器提取traceId并设置到MDC
      • 关键注意事项

在Spring Cloud微服务中,REST接口调用的 traceId传递核心是通过 HTTP请求头(Header) 携带 traceId,结合拦截器(发送端)和过滤器(接收端)实现自动传递,且不侵入业务代码。

推荐方案:基于Spring Cloud Sleuth(无侵入,官方推荐)

Spring Cloud Sleuth是Spring官方的分布式追踪组件,默认已实现traceId的生成、传递和MDC绑定,无需手动编码,完全无侵入。

1. 集成Sleuth

在微服务的pom.xml中引入依赖(以Spring Boot 2.x为例):

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
2. 核心原理
  • 发送端:Sleuth会自动拦截RestTemplateFeignClient等HTTP调用,将当前线程MDC中的traceId(默认键为X-B3-TraceId)添加到HTTP请求头中。
  • 接收端:Sleuth会拦截HTTP请求,从请求头中提取X-B3-TraceId,自动设置到当前线程的MDC中(键为traceId),供日志框架使用。
  • 自动生成:若当前线程无traceId(如请求入口),Sleuth会自动生成全局唯一的traceId
3. 日志配置(输出traceId)

logback-spring.xml(或其他日志配置文件)中,通过%X{traceId}占位符输出traceId

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%thread] %-5level %logger{50} - %msg%n</pattern></encoder>
</appender>
4. 验证
  • 服务A调用服务B的REST接口时,Sleuth会自动在请求头中添加X-B3-TraceId
  • 服务B的日志中会包含与服务A相同的traceId,实现全链路关联。

自定义实现方案(不依赖Sleuth,了解原理)

若需自定义traceId传递逻辑(如自定义Header键、生成规则),可通过发送端拦截器接收端过滤器实现。

1. 定义常量(统一Header键)
public class TraceConstant {// 自定义traceId在HTTP头中的键public static final String TRACE_ID_HEADER = "X-Trace-Id";// MDC中的键public static final String TRACE_ID_MDC_KEY = "traceId";
}
2. 发送端:通过拦截器传递traceId

发送端(调用其他服务的微服务)需要在HTTP请求发送前,将当前MDC的traceId放入请求头。

(1)RestTemplate调用场景

配置RestTemplate时添加拦截器:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;
import org.slf4j.MDC;
import java.io.IOException;
import java.util.UUID;@Configuration
public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {RestTemplate restTemplate = new RestTemplate();// 添加自定义拦截器,传递traceIdrestTemplate.getInterceptors().add(new TraceIdInterceptor());return restTemplate;}// 自定义拦截器public static class TraceIdInterceptor implements ClientHttpRequestInterceptor {@Overridepublic ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {// 1. 获取当前MDC的traceId,若不存在则生成String traceId = MDC.get(TraceConstant.TRACE_ID_MDC_KEY);if (traceId == null) {traceId = generateTraceId();}// 2. 将traceId添加到请求头HttpHeaders headers = request.getHeaders();headers.add(TraceConstant.TRACE_ID_HEADER, traceId);// 3. 继续执行请求return execution.execute(request, body);}private String generateTraceId() {return UUID.randomUUID().toString().replace("-", "");}}
}
(2)Feign调用场景

通过RequestInterceptor拦截Feign请求,添加traceId到请求头:

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.slf4j.MDC;
import java.util.UUID;@Configuration
public class FeignConfig {@Beanpublic RequestInterceptor traceIdRequestInterceptor() {return new RequestInterceptor() {@Overridepublic void apply(RequestTemplate template) {// 1. 获取或生成traceIdString traceId = MDC.get(TraceConstant.TRACE_ID_MDC_KEY);if (traceId == null) {traceId = UUID.randomUUID().toString().replace("-", "");}// 2. 添加到Feign请求头template.header(TraceConstant.TRACE_ID_HEADER, traceId);}};}
}
3. 接收端:通过过滤器提取traceId并设置到MDC

接收端(被调用的微服务)需要从HTTP请求头中提取traceId,设置到MDC,并在请求结束后清除。

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.slf4j.MDC;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class TraceIdInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 1. 从请求头提取traceIdString traceId = request.getHeader(TraceConstant.TRACE_ID_HEADER);// 2. 若不存在,可生成新的(如入口服务)if (traceId == null) {traceId = generateTraceId();}// 3. 设置到MDCMDC.put(TraceConstant.TRACE_ID_MDC_KEY, traceId);return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// 4. 请求处理完成后清除MDC(关键:避免线程池复用导致的残留)MDC.remove(TraceConstant.TRACE_ID_MDC_KEY);}private String generateTraceId() {return UUID.randomUUID().toString().replace("-", "");}
}

注册拦截器(确保生效):

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Resourceprivate TraceIdInterceptor traceIdInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 拦截所有请求registry.addInterceptor(traceIdInterceptor).addPathPatterns("/**");}
}

关键注意事项

  1. 优先级:推荐使用Spring Cloud Sleuth,它与Spring Cloud生态(如Zipkin、Feign、Gateway)无缝集成,支持更复杂的链路追踪(如spanId、调用耗时)。
  2. 入口服务处理:对于整个链路的第一个服务(如网关),若请求头中无traceId,需自动生成(Sleuth或自定义拦截器均会处理)。
  3. 线程安全:接收端必须在afterCompletion中清除MDC,避免Tomcat线程池复用导致traceId串用。
  4. 网关传递:若使用Spring Cloud Gateway,需确保网关也配置了traceId传递(Sleuth对Gateway有原生支持,自定义方案需通过GlobalFilter实现)。

通过以上方式,可在Spring Cloud微服务的REST调用中实现traceId的自动传递,全链路日志将包含相同的traceId,便于问题追踪。

http://www.dtcms.com/a/521519.html

相关文章:

  • 网站关键词符号怎么样提高网站点击率
  • 【经典书籍】《编写可读代码的艺术》精华
  • 网站推广专业术语代表性设计制作作品图片
  • 小游戏网站欣赏wordpress 在线报名系统
  • 传奇手游大型网站seo计费怎么刷关键词的
  • 启东网站建设什么是网络营销竞争的利器之一
  • 网站申请微信登录wordpress双站 中英文
  • 2510rs,rust,1.87
  • 阮一峰《TypeScript 教程》学习笔记——类
  • 建设网站的企业费用金融行业做网站需要什么
  • 拌合楼软件开发(33)多品牌车牌识别摄像头引入
  • 使用postman玩转接口测试
  • 桂林北站怎么去阳朔辽宁网站建设多少钱
  • 烟台优化网站建设企业微信邮箱登录入口
  • 做移动网站优化快速网站推广如何做的
  • 网站建设需要怎样的经营范围公司logo图片大全
  • EtherCAT状态机
  • 探究Windows图形化界面的起源与原因
  • vue 如何实现粘贴复制功能
  • 企业信息化建设如何帮助客户理解网站流量已经有了域名怎么做网站
  • 华大基因 建设网站wordpress点击折叠展开内容
  • 永康网站建设的公司苏州网站建设丨好先生科技
  • 学习笔记 | 链路预测
  • I. Imagined Holly——The 2025 ICPC Asia Xi‘an Regional Contest(2025ICPC区域赛西安站)
  • 【JUnit实战3_09】第五章:软件测试的基本原则简介
  • 安徽飞亚建设网站潍坊知名网站建设最新报价
  • 凡科建站免费版可以做什么wordpress 上传pdf
  • 肥乡专业做网站wordpress模板汉化
  • Linux学习笔记及常用运维命令
  • 【Android】横竖屏切换时生命周期变化