【服务日志链路追踪】

news2025/4/8 5:41:14

MDC+InheritableThreadLocal和spring cloud sleuth

在微服务架构中,日志链路追踪(Logback + Distributed Tracing) 是一个关键需求,主要用于跟踪请求在不同服务间的调用链路,便于排查问题。常见的实现方案有两种:

手动方案(MDC + InheritableThreadLocal)

自动化方案(Spring Cloud Sleuth + Zipkin/Jaeger)

下面从 Logback 日志集成 的角度,对比这两种方案的实现方式、优缺点及适用场景。

  1. 手动方案:MDC + InheritableThreadLocal
    核心组件
    MDC(Mapped Diagnostic Context)

Logback 提供的线程本地存储,用于存放日志变量(如 traceId)。

日志输出时自动携带 MDC 中的字段(需配置 %X{traceId})。

InheritableThreadLocal

解决异步线程(如线程池、@Async)无法继承 MDC 的问题。

实现步骤
(1) 定义 TraceContext(管理 traceId)

public class TraceContext {
    private static final InheritableThreadLocal<String> TRACE_ID = new InheritableThreadLocal<>();

    public static void setTraceId(String traceId) {
        TRACE_ID.set(traceId);
        MDC.put("traceId", traceId); // 存入 MDC,Logback 自动输出
    }

    public static String getTraceId() {
        return TRACE_ID.get();
    }

    public static void clear() {
        TRACE_ID.remove();
        MDC.remove("traceId");
    }
}

(2) 拦截器设置 traceId(HTTP 请求入口)

public class TraceInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String traceId = request.getHeader("X-Trace-Id") != null ? 
            request.getHeader("X-Trace-Id") : UUID.randomUUID().toString();
        TraceContext.setTraceId(traceId);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        TraceContext.clear(); // 防止内存泄漏
    }
}

(3) Logback 配置(输出 traceId)

<!-- logback-spring.xml -->
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

日志示例:

14:25:30.456 [http-nio-8080-exec-1] [abc123] INFO  com.example.demo.Controller - Request received

(4) 异步线程支持(线程池需额外处理)

// 普通线程
new Thread(() -> {
    log.info("Async task"); // 能继承 traceId
}).start();

// 线程池需使用 TransmittableThreadLocal(阿里开源库)
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
    log.info("ThreadPool task"); // 默认会丢失 traceId!
});

在这里插入图片描述
TransmittableThreadLocal vs InheritableThreadLocal
在这里插入图片描述

  1. 自动化方案:Spring Cloud Sleuth + Logback
    核心组件
    Spring Cloud Sleuth

自动生成 traceId 和 spanId,并通过 MDC 输出到日志。

支持 HTTP(Feign/RestTemplate)、MQ(Kafka/RabbitMQ)、gRPC 等自动传播。

Logback 集成

Sleuth 自动填充 MDC,无需手动管理。

实现步骤
(1) 引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<!-- 可选:上报到 Zipkin -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>

(2) Logback 配置(自动携带 traceId)

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] [%X{traceId:-}] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

日志示例(Sleuth 自动填充 traceId 和 spanId):

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] [%X{traceId:-}] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

(3) 跨服务调用(自动传播 traceId)
HTTP(Feign):自动添加 X-B3-TraceId Header。

MQ(Kafka):消息头自动携带追踪信息。

在这里插入图片描述

  1. 对比总结
    在这里插入图片描述

  2. 推荐选择
    简单项目:使用 MDC + InheritableThreadLocal(或 TransmittableThreadLocal)。

微服务架构:直接上 Spring Cloud Sleuth(或 OpenTelemetry),减少维护成本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2328192.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【行测】判断推理:图形推理

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;读不在三更五鼓&#xff0c;功只怕一曝十寒。 > 目标&#xff1a;掌握 图形推理 基本题型&#xff0c;并能运用到例题中。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! …

3D模型给可视化大屏带来了哪些创新,都涉及到哪些技术栈。

一、3D 模型给可视化大屏带来的创新 更直观的视觉体验 传统的可视化大屏主要以二维图表和图形的形式展示数据&#xff0c;虽然能够传达一定的信息&#xff0c;但对于复杂的场景和数据关系&#xff0c;往往难以直观地呈现。而 3D 模型可以将数据以三维立体的形式展示出来&#…

Unity HDRP管线用ShaderGraph还原Lit,方便做拓展;

里面唯一的重点就是判断有无这张复合图&#xff0c;我用的是颜色判断&#xff1a; float Tex TexCol.r*TexCol.g*TexCol.b*TexCol.a; if(Tex 1) { IsOrNot 1; } else { IsOrNot 0; } 其他的正常解码就行&#xff0c;对了法线贴图孔位记得设置成normal&#xff0c;不然的话…

绝缘升级 安全无忧 金能电力环保绝缘胶垫打造电力安全防护新标杆

在电力安全领域&#xff0c;一块看似普通的胶垫&#xff0c;却是守护工作人员生命安全的“第一道防线”。近年来&#xff0c;随着电网设备升级和环保要求趋严&#xff0c;传统绝缘胶垫有异味、易老化、绝缘性能不足等问题逐渐暴露。为此&#xff0c;金能电力凭借技术创新推出新…

Linux命令-iotop

iotop 命令 iotop 是一个用于实时监控磁盘 I/O 活动的工具&#xff0c;可以显示哪些进程正在使用磁盘资源。 参数 描述 –version 显示程序版本号并退出 -h, --help 显示此帮助消息并退出 -o, --only 仅显示实际进行 I/O 操作的进程或线程 -b, --batch 非交互模式&#xff0c;适…

QTableWidget 中insertRow(0)(头插)和 insertRow(rowCount())(尾插)的性能差异

一、目的 在 Qt 的 QTableWidget 中&#xff0c;insertRow(0) &#xff08;头插&#xff09;和 insertRow(rowCount())&#xff08;尾插&#xff09;在性能上存在显著差异。 二、QAbstractItemModel:: insertRows 原文解释 QAbstractItemModel Class | Qt Core 5.15.18 AI 解…

【万字总结】前端全方位性能优化指南(完结篇)——自适应优化系统、遗传算法调参、Service Worker智能降级方案

前言 自适应进化宣言 当监控网络精准定位病灶&#xff0c;真正的挑战浮出水面&#xff1a;系统能否像生物般自主进化&#xff1f; 五维感知——通过设备传感器实时捕获环境指纹&#xff08;如地铁隧道弱光环境自动切换省电渲染&#xff09; 基因调参——150个性能参数在遗传算…

不绕弯地解决文件编码问题,锟斤拷烫烫烫

安装python对应库 pip install chardet 检测文件编码 import chardet# 检测文件编码 file_path rC:\Users\AA\Desktop\log.log # 这里放文件和文件绝对路径 with open(file_path, rb) as f:raw_data f.read(100000) # 读取前10000个字节result chardet.detect(raw_data)e…

高密度任务下的挑战与破局:数字样机助力火箭发射提效提质

2025年4月1日12时&#xff0c;在酒泉卫星发射中心&#xff0c;长征二号丁运载火箭顺利升空&#xff0c;成功将一颗卫星互联网技术试验卫星送入预定轨道&#xff0c;发射任务圆满完成。这是长征二号丁火箭的第97次发射&#xff0c;也是长征系列火箭的第567次发射。 执行本次任务…

QT Quick(C++)跨平台应用程序项目实战教程 6 — 弹出框

目录 1. Popup组件介绍 2. 使用 上一章内容完成了音乐播放器程序的基本界面框架设计。本小节完成一个简单的功能。单击该播放器顶部菜单栏的“关于”按钮&#xff0c;弹出该程序的相关版本信息。我们将使用Qt Quick的Popup组件来实现。 1. Popup组件介绍 Qt 中的 Popup 组件…

KisFlow-Golang流式实时计算案例(四)-KisFlow在消息队列MQ中的应用

Golang框架实战-KisFlow流式计算框架专栏 Golang框架实战-KisFlow流式计算框架(1)-概述 Golang框架实战-KisFlow流式计算框架(2)-项目构建/基础模块-(上) Golang框架实战-KisFlow流式计算框架(3)-项目构建/基础模块-(下) Golang框架实战-KisFlow流式计算框架(4)-数据流 Golang框…

leetcode:1582. 二进制矩阵中的特殊位置(python3解法)

难度&#xff1a;简单 给定一个 m x n 的二进制矩阵 mat&#xff0c;返回矩阵 mat 中特殊位置的数量。 如果位置 (i, j) 满足 mat[i][j] 1 并且行 i 与列 j 中的所有其他元素都是 0&#xff08;行和列的下标从 0 开始计数&#xff09;&#xff0c;那么它被称为 特殊 位置。 示…

Cline – OpenRouter 排名第一的CLI 和 编辑器 的 AI 助手

Cline – OpenRouter 排名第一的CLI 和 编辑器 的 AI 助手&#xff0c;Cline 官网&#xff1a;https://github.com/cline/cline Star 37.8k ps&#xff0c;OpenRouter的网址是&#xff1a;OpenRouter &#xff0c;这个排名第一&#xff0c;据我观察&#xff0c;是DeepSeek v3…

Mock.js虚拟接口

Vue3中使用Mock.js虚拟接口数据 一、创建项目 pnpm创建vite的项目,通过 PNPM来简化依赖管理。若还没有安装 PNPM&#xff0c;可以通过 npm来安装&#xff1a; 安装 PNPM npm install -g pnpm//使用国内镜像加速pnpm add -g pnpmlatestpnpm config set registry http://regis…

LoRa模块通信距离优化:如何实现低功耗覆盖30公里无线传输要求

在物联网&#xff08;IoT&#xff09;快速发展的今天&#xff0c;LoRa&#xff08;Long Range&#xff09;技术作为一种基于扩频调制的远距离无线通信技术&#xff0c;因其远距离通信、低功耗和强抗干扰能力等优势&#xff0c;在农业监测、城市智能管理、环境监测等多个领域得到…

OpenCV 从入门到精通(day_05)

1. 模板匹配 1.1 什么是模板匹配 模板匹配就是用模板图&#xff08;通常是一个小图&#xff09;在目标图像&#xff08;通常是一个比模板图大的图片&#xff09;中不断的滑动比较&#xff0c;通过某种比较方法来判断是否匹配成功。 1.2 匹配方法 rescv2.matchTemplate(image, …

OpenRouter开源的AI大模型路由工具,统一API调用

简介 ‌OpenRouter是一个开源的路由工具‌&#xff0c;它可以绕过限制调用GPT、Claude等国外模型。以下是对它的详细介绍&#xff1a; 一、主要功能 OpenRouter专注于将用户请求智能路由到不同的AI模型&#xff0c;并提供统一的访问接口。它就像一个“路由器”&#xff0c;能…

zabbix监控网站(nginx、redis、mysql)

目录 前提准备&#xff1a; zabbix-server主机配置&#xff1a; 1. 安装数据库 nginx主机配置&#xff1a; 1. 安装nginx redis主机配置&#xff1a; 1. 安装redis mysql主机配置&#xff1a; 1. 安装数据库 zabbix-server&#xff1a; 1. 安装zabbix 2. 编辑配置文…

蓝桥杯冲刺

例题1&#xff1a;握手问题 方法1&#xff1a;数学推理(简单粗暴&#xff09; 方法2&#xff1a;用代码实现方法1 #include<iostream> using namespace std; int main() {int result 0;for (int i 1; i < 49; i){for (int j i 1; j < 50; j){//第i个人与第j个…

Spring Security(maven项目) 3.1.0

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…