dubbo项目traceId链路传递(MDC方案及重复traceId处理)

news2024/11/19 22:47:55

1.traceId用途

        主要用于项目dubbo接口调用链日志追踪使用,可以获取完整的链路日志,协助排查问题。

2.traceId传递及代码实现

        本方案是基于 org.slf4j.MDC 进行实现,会出现线程池中线程复用导致traceId重复问题,后面会说解决方案。

  • web项目(CONSUMER)

    • com.alibaba.dubbo.rpc.Filter 文件,路径在src\main\resources\META-INF\dubbo目录下面,文件内容就是对应项目中指定的过滤器类路径
      • globalTraceFilter=com.xxx.filter.GlobalTraceFilter

  • GlobalTraceFilter类里面代码如下,实现dubbo的Filter接口:

    package com.xxx.filter;
    
    import lombok.extern.slf4j.Slf4j;
    import org.apache.dubbo.common.constants.CommonConstants;
    import org.apache.dubbo.common.extension.Activate;
    import org.apache.dubbo.rpc.*;
    import org.slf4j.MDC;
    
    import java.util.UUID;
    
    /**
     * @Description 过滤器传递tradeId(消费者)
     * @Version v1.0
     */
    @Activate(group = {CommonConstants.CONSUMER})
    @Slf4j
    public class GlobalTraceFilter implements Filter {
        private static final String TRACE_ID = "TraceId";
    
        @Override
        public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
            RpcContext rpcContext = RpcContext.getContext();
            String traceId;
            if (rpcContext.isConsumerSide()) {
                traceId = MDC.get(TRACE_ID);
                if (traceId == null) {
                    traceId = UUID.randomUUID().toString().replace("-", "");
                }
                MDC.put(TRACE_ID, traceId);
                rpcContext.setAttachment(TRACE_ID, traceId);
            }
            return invoker.invoke(invocation);
        }
    }
    
  • logback-spring.xml配置
     

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    
        <springProperty scope="context" name="PORT" source="server.port" default = ""/>
        <property name="log_dir" value="/data/logs/sso/${PORT}" />
        <property name="default_log" value="${log_dir}/xxx-web"/>
        <property name="error_log" value="${log_dir}/xxx-web-error"/>
    
    
        <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
            <encoder charset="UTF-8">
                <pattern>
                    %d{yyyy-MM-dd HH:mm:ss.SSS},[%X{TraceId}] [%thread] %highlight(%-5level) %cyan(%logger{15}) - %highlight(%msg) %n%exception
                </pattern>
            </encoder>
        </appender>
    
    
           <!-- 默认日志 按日切分 -->
        <appender name="default" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${default_log}</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${default_log}.%d{yyyy-MM-dd}</fileNamePattern>
                <maxHistory>60</maxHistory>
                <totalSizeCap>50GB</totalSizeCap>
            </rollingPolicy>
            <encoder>
                <pattern>
                    %d{yyyy-MM-dd HH:mm:ss.SSS},[%X{TraceId}] [%thread] %-5level %logger{36} %method:%L - %msg %n
                </pattern>
            </encoder>
        </appender>
    
    
        <!-- ERROR -->
        <appender name="common-error" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${error_log}</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${error_log}.%d{yyyy-MM-dd}</fileNamePattern>
                <maxHistory>60</maxHistory>
                <totalSizeCap>10GB</totalSizeCap>
            </rollingPolicy>
            <encoder>
                <pattern>
                    %d{yyyy-MM-dd HH:mm:ss.SSS},[%X{TraceId}] [%thread] %-5level %logger{36} %method:%L - %msg%n%exception
                </pattern>
            </encoder>
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERROR</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
        </appender>
    	<logger name="com.xxx" level="DEBUG"/>
        <!-- ROOT -->
        <root level="INFO">
            <appender-ref ref="default"/>
            <appender-ref ref="common-error"/>
            <appender-ref ref="console"/>
        </root>
    
    </configuration>
    • api项目(CONSUMER&PROVIDER)

      • com.alibaba.dubbo.rpc.Filter 文件,路径在src\main\resources\META-INF\dubbo目录下面,文件内容就是对应项目中指定的过滤器类路径
        • globalTraceFilter=com.xxx.filter.GlobalTraceFilter

  • GlobalTraceFilter类里面代码如下,实现dubbo的Filter接口:
     

    package com.xxx.filter;
    
    import org.apache.dubbo.common.constants.CommonConstants;
    import org.apache.dubbo.common.extension.Activate;
    import org.apache.dubbo.rpc.*;
    import org.slf4j.MDC;
    
    import java.util.UUID;
    
    /**
     * @Description 过滤器传递tradeId(消费者和生产者)
     * @Version v1.0
     */
    @Activate(group = {CommonConstants.CONSUMER, CommonConstants.PROVIDER})
    public class GlobalTraceFilter implements Filter {
        private static final String TRACE_ID = "TraceId";
    
        @Override
        public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
            RpcContext rpcContext = RpcContext.getContext();
            String traceId;
            if (rpcContext.isConsumerSide()) {
                traceId = MDC.get(TRACE_ID);
                if (traceId == null) {
                    traceId = UUID.randomUUID().toString();
                }
                rpcContext.setAttachment(TRACE_ID, traceId);
            }else if (rpcContext.isProviderSide()) {
                traceId = rpcContext.getAttachment(TRACE_ID);
                if (traceId == null) {
                    traceId = UUID.randomUUID().toString();
                }
                MDC.put(TRACE_ID, traceId);
            }
            return invoker.invoke(invocation);
        }
    }

  • logback-spring.xml配置和上面一样

3.traceId重复的处理

通过AOP进行处理,controller方法执行完后清除MDC,避免日志线程池中的线程复用导致MDC中traceId还存在则不会生成新的traceId;

web项目中RequestTraceIdAspect类代码如下:

package com.xxx.aspectj;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

/**
 * @Description
 * @Create 2023/8/31
 */
@Aspect
@Component
public class RequestTraceIdAspect {
    @After("execution(public * com.xxx.controller..*.*(..)) && !execution(* com.xxx.controller.BaseController.*(..))")
    public void afterRequest() {
        // 在请求结束时执行的逻辑,清空MDC中的TraceId,避免线程池中因线程复用导致上次请求的TraceId在后续请求中重复使用
        MDC.clear();
    }
}

特别说明一下 !execution(* com.xxx.controller.BaseController.*(..))排查BaseController中的方法,因为这里项目中Controller有继承BaseController做通用处理,会先调用里面的方法,如果在里面就清空了MDC,再到对应Controller执行真正业务逻辑的时候就没有traceId了;如果没有这种继承关系就不需要这段了

4.mybatis日志未记录到日志中的处理

现象如下图,api项目中sql日志并未显示traceId

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis日志标准输出改为如下通过slf4j的日志实现输出即可
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.slf4j.Slf4jImpl

希望能帮到各位小伙伴哦~

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

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

相关文章

unity 发布apk,在应用内下载安装apk(用于更大大版本)

*注意事项&#xff1a; 1&#xff0c;andriod 7.0 和 android 8.0是安卓系统的分水岭&#xff0c;需要分开来去实现相关内容2&#xff0c;注意自己的包名&#xff0c;在设置一些共享文件的时候需要放自己的包名3,以下是直接用arr包放入unity中直接使用的&#xff0c;不需要导入…

QTday2(信号与槽机制——很重要!!!)

一、Xmind整理&#xff1a; 二、上课笔记整理&#xff1a; 1.信号与槽 class Widget : public QWidget {Q_OBJECT //信号与槽的元对象signals:void my_signal(); //自定义信号函数public slots:void my_slot(); //自定义的槽函数public:Widget(Q…

码云使用记录

码云使用记录 主要步骤 1、https://gitee.com 注册 2、下载Git 3、配置SSH 4、创建远程仓库 5、切到本地项目目录下将本地项目推到远程 前两步根据提示进行即可&#xff0c;下面从第三步开始讲解 3、配置SSH&#xff08;用于提交代码和更新代码&#xff09; https://gitee.…

IDEA全局统一设置Maven

原来每次打开新建的项目都需要经过 File-> Settings 重新配置maven&#xff0c;这样很不爽 然而经过 File-> New Projects Setup -> Settings for New Projects 后&#xff0c;再如上图配置后就全局设置好了

文件包含漏洞利用的几种方法

文章目录 安装环境启动环境漏洞花式利用蚁剑连接图片马读取敏感文件&#xff08;hosts&#xff09;读取该网站的php源码 代码审计 安装环境 安装phpstudy&#xff0c;下载MetInfo 5.0.4版本软件&#xff0c;复制到phpstudy目录下的www目录中。 打开phpstudy&#xff0c;访问浏…

Ubuntu系统下配置 Qt Creator 输入中文、配置软件源的服务器地址、修改Ubuntu系统时间

上篇介绍了Ubuntu系统下搭建QtCreator开发环境。我们可以发现安装好的QtCreator不能输入中文&#xff0c;也没有中文输入法供选择&#xff0c;这里需要进行设置。 文章目录 1. 配置软件源的服务器地址2. 先配置Ubuntu系统语言&#xff0c;设置为中文3. 安装Fcitx插件&#xff…

Android 下第一个fragment app 先Java 后Kotlin

看着视频学习的&#xff0c;Fragment&#xff1a;3.Fragment使用方法_哔哩哔哩_bilibili 在android studio 下新建一个工程&#xff0c;类型是 Empty View Activity&#xff0c;本身就有一个Activity。就有文件MainActivity.java 或者kt&#xff0c;还有一个layout 文件&#…

如何给小程序会员添加档案记录

​给小程序会员添加档案记录&#xff0c;可以帮助商家更好地管理会员信息和提供个性化的服务。下面就具体介绍怎么设置档案记录。 1. 找到指定的会员卡。在管理员后台->会员管理处&#xff0c;找到需要添加档案记录的会员卡。也支持对会员卡按卡号、手机号和等级进行搜索。…

unity 之 如何获取父物体与子物体

文章目录 获取父物体获取子物体 获取父物体 在Unity中&#xff0c;你可以使用Transform组件的属性来获取对象的父物体。以下是在C#脚本中如何获取父物体的示例代码&#xff1a; using UnityEngine;public class GetParentExample : MonoBehaviour {void Start(){// 获取当前物…

人生中的孤独

孤独是一种深刻而痛苦的情感状态&#xff0c;在这个喧嚣而充满人群的世界中&#xff0c;许多人都曾经或正在经历孤独的阶段。 孤独并不仅仅是身边缺乏他人的陪伴&#xff0c;更是一种内心的空虚和失落。 孤独的人生可能来源于各种原因。 有些人可能因为缺乏亲密的人际关系&…

基于STM32的空气质量检测LCD1602显示报警仿真设计(仿真+程序+讲解)

本设计 基于STM32的空气质量检测报警仿真设计(仿真程序讲解&#xff09; 1.主要功能2.仿真3. 程序4. 资料清单&下载链接 基于STM32的空气质量检测报警仿真设计(仿真程序讲解&#xff09; 仿真图proteus 8.9 程序编译器&#xff1a;keil 5 编程语言&#xff1a;C语言 设…

信息安全——密钥管理

根据近代密码学观点&#xff0c;密钥体制的安全应当只取决于密钥的安全&#xff0c;而不取决于对密码算法的保密。因此密钥管理是至关重要的。 从技术上讲&#xff0c;密钥管理包括密钥的产生、存储、分配、组织、使用、更换和销毁等一系列技术问题。每个密钥都有其生命周期&a…

医学影像软件 Sante DICOM Viewer Crack

医学影像软件 Sante DICOM Viewer Crack Sante DICOM Viewer是用于恢复&#xff0c;查看&#xff0c;存储&#xff0c;存档&#xff0c;管理和刻录医学图像的最佳软件之一。它是专业的DICOM显示器&#xff0c;转换器&#xff0c;PACS客户端&#xff0c;迷你PACS服务器&#xff…

【0831作业】QTday2 加载资源文件、信号与槽机制(非常重要)、界面跳转

一、思维导图 二、今日面试题 三、今日知识回顾 1 信号与槽的连接 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QDebug> #include<QPushButton> #include<QTextToSpeech>//文本转语音类 QT_BEGIN_NAMESPACE namespace Ui { c…

比较opencv,pillow,matplotlib,skimage读取图像的速度比较

上面这些库都被广泛用于图像处理和计算机视觉任务&#xff1b; 不同的图像读取库&#xff08;OpenCV&#xff0c;Pillow&#xff0c;matplotlib和skimage&#xff09;的读取速度&#xff0c;是怎么样的一个情况&#xff1f; 下面分别从读取速度&#xff0c;以及转换到RGB通道…

端到端自动驾驶综述

End-to-end Autonomous Driving: Challenges and Frontiers 文章脉路 Introduction 从经典的模块化的方法到端到端方法的一个对比, 讲了各自的优缺点, 模块化的好处是各个模块都有自己明确的优化的目标, 可解释性较强, 且容易debug, 缺点是各个模块优化的目标并不是最终的驾…

智能电销机器人,主要体现的价值是什么

21世纪科技的迅速发展&#xff0c;人工智能逐渐走入大家的视线&#xff0c;越来越多的机器人出现在我们生活中。见的最多的有电销公司的智能语音机器人、在仓库拣货打包的机器人、商场店铺供娱乐对话的机器人。机器人活跃在各行各业中&#xff0c;降低了人工成本&#xff0c;代…

Realsense D435i实时运行ORB-SLAM3

三、ORB-SLAM3的ROS编译&#xff08;Realsense D435i实时跑ORB-SLAM3&#xff09; 四、ORB-SLAM3的ROS运行 3. ROS运行单目demo 创建ROS工作空间,初始化 mkdir -p ~/catkin_ws/src cd ~/catkin_ws catkin_make source devel/setup.bash echo "source ~/catkin_ws/devel/…