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

山东省建设厅制一网站沈阳专业网站建设公司排名

山东省建设厅制一网站,沈阳专业网站建设公司排名,wordpress英文站源码,网站源码 后台网关 MDC 过滤器方案通过在网关层统一生成 TraceId,再通过过滤器在各服务间透传,实现全链路日志追踪。以下是具体实现步骤,包含网关生成、服务接收、跨线程传递等关键细节: 一、网关层:生成并传递 TraceId&#xff08…

网关 + MDC 过滤器方案通过在网关层统一生成 TraceId,再通过过滤器在各服务间透传,实现全链路日志追踪。以下是具体实现步骤,包含网关生成、服务接收、跨线程传递等关键细节:

一、网关层:生成并传递 TraceId(以 Spring Cloud Gateway 为例)

作用:所有请求进入系统的第一个入口生成 TraceId,确保全链路唯一。

1. 添加依赖(若未引入)
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
2. 编写全局过滤器
import org.slf4j.MDC;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.UUID;@Configuration
public class TraceIdGatewayConfig {@Beanpublic GlobalFilter traceIdFilter() {return (exchange, chain) -> {// 1. 生成 TraceId(去掉 UUID 中的横线,更简洁)String traceId = UUID.randomUUID().toString().replace("-", "");// 2. 放入 MDC,供网关自身日志使用MDC.put("traceId", traceId);// 3. 写入请求头,传递给下游服务ServerWebExchange modifiedExchange = exchange.mutate().request(exchange.getRequest().mutate().header("X-Trace-Id", traceId)  // 约定 header 键为 X-Trace-Id.build()).build();// 4. 执行后续过滤链,完成后清除 MDC(避免 Netty 线程复用导致的污染)return chain.filter(modifiedExchange).doFinally(signalType -> MDC.clear());};}// 设置过滤器优先级(最高,确保第一个执行)@Beanpublic Ordered traceIdFilterOrder() {return () -> Ordered.HIGHEST_PRECEDENCE;}
}

二、下游服务:接收并透传 TraceId(所有业务服务通用)

作用:从请求头获取 TraceId,放入当前线程的 MDC,确保日志能打印;同时在调用其他服务时传递下去。

1. 编写 Servlet 过滤器(Spring Boot Web 服务)
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.UUID;@Component
public class TraceIdServletFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;// 1. 从请求头获取 TraceId,若没有则生成(应对直接访问服务的场景)String traceId = httpRequest.getHeader("X-Trace-Id");if (traceId == null || traceId.isEmpty()) {traceId = UUID.randomUUID().toString().replace("-", "");}// 2. 放入 MDC,供当前服务日志使用MDC.put("traceId", traceId);try {// 3. 执行后续逻辑chain.doFilter(request, response);} finally {// 4. 清除 MDC,避免 Tomcat 线程池复用导致的脏数据MDC.clear();}}
}
2. 配置日志模板(logback-spring.xml)

在日志格式中加入 [%X{traceId}],示例:

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{traceId}] %logger{50} - %msg%n</pattern></encoder>
</appender>

此时服务日志会自动带上 TraceId,形如:

2025-07-31 15:00:00.123 [http-nio-8080-exec-1] INFO [a1b2c3d4e5f67890] com.example.Service - 处理订单逻辑

三、跨服务调用:确保 TraceId 透传(关键!)

当服务 A 调用服务 B 时,需手动将当前 MDC 中的 TraceId 放入请求头,否则链路会中断。

1. RestTemplate 调用场景
import org.slf4j.MDC;
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 java.io.IOException;
import java.util.Collections;// 配置 RestTemplate 拦截器,自动添加 TraceId 头
@Configuration
public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {RestTemplate restTemplate = new RestTemplate();restTemplate.setInterceptors(Collections.singletonList(new ClientHttpRequestInterceptor() {@Overridepublic ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)throws IOException {// 从 MDC 获取 TraceId,添加到请求头String traceId = MDC.get("traceId");if (traceId != null) {request.getHeaders().add("X-Trace-Id", traceId);}return execution.execute(request, body);}}));return restTemplate;}
}
2. OpenFeign 调用场景
import feign.RequestInterceptor;
import org.slf4j.MDC;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FeignConfig {@Beanpublic RequestInterceptor traceIdInterceptor() {return template -> {// 从 MDC 获取 TraceId,添加到 Feign 请求头String traceId = MDC.get("traceId");if (traceId != null) {template.header("X-Trace-Id", traceId);}};}
}

四、跨线程场景:解决异步任务 TraceId 丢失

当使用线程池、CompletableFuture 等异步操作时,子线程默认无法继承父线程的 MDC 数据,需手动传递:

1. 线程池包装类(推荐)
import org.slf4j.MDC;
import java.util.Map;
import java.util.concurrent.*;public class TraceIdThreadPoolExecutor extends ThreadPoolExecutor {// 构造方法复用父类public TraceIdThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue) {super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);}@Overridepublic void execute(Runnable command) {// 获取父线程 MDC 上下文Map<String, String> context = MDC.getCopyOfContextMap();super.execute(() -> {try {// 子线程设置 MDC 上下文if (context != null) {MDC.setContextMap(context);}command.run();} finally {// 清除子线程 MDCMDC.clear();}});}
}
2. 使用方式
// 用包装类创建线程池,替代原生 ThreadPoolExecutor
ExecutorService executor = new TraceIdThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>()
);// 提交任务时,子线程日志会自动带上 TraceId
executor.submit(() -> {log.info("异步处理任务...");  // 日志中包含父线程的 TraceId
});

五、验证与效果

  1. 发起请求:通过网关访问任意接口(如 http://网关地址/order/create)。
  2. 查看日志:在网关、服务 A、服务 B 的日志中搜索同一个 TraceId,确认链路贯通。
  3. 异常排查:当出现问题时,只需 grep 某个 TraceId,即可获取全链路的日志上下文。

核心要点总结

  • 网关生成:确保入口唯一,避免分布式环境下 TraceId 冲突。
  • 过滤器透传:所有服务必须添加过滤器,且日志模板包含 %X{traceId}
  • 跨服务调用:RestTemplate/Feign 必须加拦截器,否则调用下游时 TraceId 丢失。
  • 异步场景:线程池需包装,手动传递 MDC 上下文,否则子线程日志无 TraceId。
场景分类具体场景核心问题解决方案侵入性适用范围
跨服务调用HTTP调用(Feign)服务间请求头未自动携带TraceId配置Feign拦截器,自动从MDC获取并设置X-Trace-IdSpring Cloud微服务
RPC调用(Dubbo)分布式调用中上下文丢失实现Dubbo过滤器,通过Attachment传递TraceId,Provider端自动设置MDCDubbo微服务
消息队列(Kafka/RabbitMQ)消息生产/消费链路断裂生产者拦截器添加TraceId到消息头,消费者拦截器读取并设置MDC基于消息队列的异步通信
异步场景线程池(ThreadPool)子线程无法继承父线程MDC自定义线程池,提交任务时捕获父线程MDC,子线程执行前恢复所有线程池异步任务
@Async注解Spring异步方法默认不传递MDC使用自定义线程池(同上)作为@Async的执行器Spring框架异步方法
CompletableFuture链式调用中线程切换导致TraceId丢失封装CompletableFuture工具类,自动传递MDC上下文Java原生异步编程
基础场景网关入口全链路TraceId生成源头不统一网关全局过滤器生成唯一TraceId,写入请求头并设置MDC有网关的分布式系统
单体服务内部单个服务内日志无统一TraceId过滤器从请求头(或生成)TraceId,设置到MDC,日志模板包含%X{traceId}单体服务或微服务节点
特殊场景定时任务(Quartz)无请求触发,无初始TraceId任务执行时自动生成TraceId并设置MDC定时任务、后台任务
跨语言调用(如Java→Python)不同语言间上下文传递格式不统一约定X-Trace-Id头,Python端通过中间件(如Flask/Django过滤器)接收并记录多语言混合架构

通过这套方案,可在10分钟内实现轻量级全链路追踪,无需引入复杂组件,适合中小团队快速落地。

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

相关文章:

  • 17做网店这个网站做起多少钱wordpress 框架选择
  • 企业展示网站 数据库设计网站重购
  • 湖南平台网站建设设计php网站开发说明文档
  • 个人网站主页设计教程ui培训费用
  • 进口跨境电商网站制作坚决把快准严细实要求落实到位
  • 计算机发展史之阿达·洛芙莱斯
  • 海搜网做的网站怎么样帮企业做网站的
  • 首钢建设二建设公司网站哪些网站的做的好看
  • 成品网站怎么被百度收录实验仪器销信应做何网站
  • 商会联盟网站建设方案有哪些做兼职的设计网站有哪些工作内容
  • 公司网站建设方案拓扑图高端网站
  • 英语工作室网站怎么做平面广告设计培训
  • 建网站找哪个平台好呢wordpress 评论 作者
  • 最优惠的手机网站建设网站空间买什么的好
  • 做财经比较好的网站有哪些公众号开发主要做什么
  • 池州城乡住房建设厅网站建筑网片报价公式
  • 个人网站是什么意思《网站建设方案》
  • 免费无限建站方庄网站建设公司
  • 做电影资源网站有哪些wordpress手机接口
  • wordpress 网站标题设置zencart 网站换域名
  • 做英文小说网站开发网站 公司
  • 江苏连云港网站制作公司建设工程信息网官网入口
  • 空气源热泵热水器网站建设机关 网站 建设方案
  • ospf cost 概念及题目
  • sql数据库做的网站怎么发布百度收录网站链接入口
  • C++_继承与多态双双环绕,正确理解“派生类怎么‘继承’基类的成员函数”(1/2)
  • 网站可以做软著吗网站制作品牌公司
  • 全球最热门网站网站建设推广方案策划书
  • 免费建站资源青岛网站建设官网
  • 策划的网站云南省建设厅网站发文