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

一次解决ForkJoinPool日志追踪的辛酸经历

本文主要分享了一次解决ForkJoinPool日志追踪的辛酸经历。历时3个月终于找到通用的解决方案,以此文分享给有需要的你。

一、需求背景

1.某日,某同事根据日志ID排查生产环境问题过程中,发现日志不全

2.经排查发现中间有很多线程为ForkJoinPool.commonPool-worker的日志ID是丢失的

3.经代码review,发现这些丢失日志ID的log.info都是在parallelStream代码块中的

4.经了解,因为使用了parallelStream并发处理集合数据,这样能够提升接口性能,并且这个功能是jdk提供的,使用非常方便

以下为简化版的代码demo

经测试,发现在parallelStream的log.info无法正确的打印日志ID,那么在生产环境中,日志ID的丢失意味着日志排查问题变得困难,如下图所示

二、原因分析

为了提升接口性能,使用并发编程加快查询速度的确是比较不错的方案。

日志ID是使用org.slf4j.MDC进行传递的,经阅读源码,发现底层是使用ThreadLocal来进行数据存储的,多线程情况下,子线程无法访问到主线程的日志ID

并发编程项目中通常有2种用法:

1.使用线程池,如ThreadPoolExecutor、ThreadPoolTaskExecutor,可以自己new一个实例,这样的话可以通过自定义子类来做日志ID传递(这种方式已解决,具体可阅文章,这里就不详说了:https://www.toutiao.com/article/7126056949267268108)

2.使用ForkJoinPool,不是由自己new实例,而是jdk封装好的。例如CompletableFuture、list.parallelStream()、list.stream().parallel()等,底层都是使用了ForkJoinPool作为线程池实现(为了找到通用的解决方案,历时3个月)

>>> 那如何解决ForkJoinPool这个日志ID丢失的问题?

三、临时方案

当时无法在短时间内快速找到通用解决方案,所以想了1种临时方案:通过变量的方式传递到list.parallelStream()内部

如下图,这种方案需要改动代码

为什么要加subTraceId == null的判断?

答:主线程也会作为ForkJoinPool执行的一部分,主线程的日志ID不能清,否则后续的日志ID会丢失

四、寻找通用方案

1.方向错误,努力白费(辛酸经历,中途还想过放弃寻找通用方案)

方向1:参考ThreadPoolExecutor、ThreadPoolTaskExecutor,想办法自己new一个ForkJoinPool的实例,然后添加到spring容器使用

结果:最终发现ForkJoinPool是内部实现了1个静态的实例common从而告败

方向2:使用javaagent的方式修改ForkJoinPool或者其任务 ForkJoinTask等相关类的字节码,此想法来自一篇好文:一次「找回」TraceId的问题分析与过程思考(一次「找回」TraceId的问题分析与过程思考)

结果:最终发现字节码框架Javassist底层对包名以java.开头的所有类进行了保护,而ForkJoinPool的包名java.util.concurrent,所以字节码修改方案也不通了

2.求助网友,集思广益

真的挺感谢这位‘新手村NPC’网友,给我提供了1个思路:竟然修改ForkJoinPool的思路走不通,那就尝试修改日志组件

3.修改日志组件

1.前面说过MDC底层是使用ThreadLocal来进行数据存储的,这就让我想到了阿里的TransmittableThreadLocal,能够在父子线程之间传递数据

先测试一下TransmittableThreadLocal能否在list.parallelStream()内部正确传递数据

注:需要在启动命令上加上:-javaagent:path/to/transmittable-thread-local-2.x.x.jar(替换为你maven路径中jar路径即可),否则会读取不到,因为TransmittableThreadLocal是基于字节码javaagent来实现的

结果:输出的值始终保持一致

2.修改MDC

MDC的ThreadLocal在哪里?通过断点的方式找到了MDCAdapter的实例LogbackMDCAdapter(其成员变量copyOnThreadLocal)

有没有办法在初始化时替换掉这个MDCAdapter的实例?MDCAdapter下面的MDCAdapter不是public的,只有getMDCAdapter方法而没有setMDCAdapter方法。

于是网上查询相关资料,方案是在项目中写个org.slf4j的包,然后通过以下方式赋值,因为同包下可访问(不得不说这操作挺骚的,佩服,这些知识点都忘了)

然后通过TtlMdcListener对TtlMDCAdapter进行实例化

logback.xml配置文件中增加TtlMdcListener的实例化

<contextListener class="com.ofpay.logback.TtlMdcListener"/>

这2个简单的类,既可以自己实现,也可以使用开源的maven,实现原理是一样的

<dependency><groupId>com.ofpay</groupId><artifactId>logback-mdc-ttl</artifactId><version>1.0.2</version>
</dependency>

于是,在完全不改业务代码的情况下,日志ID正确地传递下来了

测试结果:

怎么样?如果你觉得有用的话,还不快快收藏起来!!!

附:涉及的代码目录

github: https://github.com/897665787/springcloud-template

gitee:springcloud-template: 一个基于springcloud netflix微服务框架,记录了关于微服务开发的一些最佳应用,欢迎大家学习指导。

springcloud-template

└── template-common

     └──src/main/resources

          └── logback-conf-base.xml-- 日志配置

     └──pom.xml-- 引用logback-mdc-ttl

└── template-web

     └──controller

          └── TraceIdController-- 日志ID测试demo

相关文章:

一次解决ForkJoinPool日志追踪的辛酸经历

本文主要分享了一次解决ForkJoinPool日志追踪的辛酸经历。历时3个月终于找到通用的解决方案&#xff0c;以此文分享给有需要的你。 一、需求背景 1.某日&#xff0c;某同事根据日志ID排查生产环境问题过程中&#xff0c;发现日志不全 2.经排查发现中间有很多线程为ForkJoinP…...

VM使用教程--SDK取图 视频笔记

本笔记均由海康机器人官网的V学院视频中记录所得&#xff0c;属于省流大师了[doge] 图像采集 图像采集包括1图像源&#xff0c;2多图采集&#xff0c;3输出图像&#xff0c;4缓存图像&#xff0c;5光源 1图像源 图像源包括本地图像&#xff0c;相机采图&#xff0c;SDK 本…...

11.spring boot 启动源码(一)

目录 概述SpringApplication静态方法构造方法run 实例方法配置文件Actuator 工作原理*EndpointAutoConfigurationBeansEndpointAutoConfigurationShutdownEndpointAutoConfiguration结束概述 spring boot 版本 2.6.13 spring boot 启动源码(一) 涉及 SpringApplication 中静态…...

【微服务】springcloud集成sleuth与zipkin实现链路追踪

目录 一、前言 二、分布式链路调用问题 三、链路追踪中的几个概念 3.1 什么是链路追踪 3.2 常用的链路追踪技术 3.3 链路追踪的几个术语 3.3.1 span ​编辑 3.3.2 trace 3.3.3 Annotation 四、sluth与zipkin概述 4.1 sluth介绍 4.1.1 sluth是什么 4.1.2 sluth核心…...

数学建模-预测人口数据

目录 中国09~18年人口数据 创建时间 绘制时间序列图 使用专家建模器 得到结果 预测结果 残差的白噪声检验 中国09~18年人口数据 创建时间 路径&#xff1a;数据-> 定义日期和时间 绘制时间序列图 使用专家建模器 看看spss最终判断是那个模型最佳的契合 得到结果 预…...

SpringBoot 集成 Canal 基于 MySQL 做数据同步

一、canal 组件关系 下载地址&#xff1a;https://github.com/alibaba/canal/releases/download/canal-1.1.7/ 这里面主要的有两个 canal.deployer-1.1.7.tar.gz 和 canal.adapter-1.1.7.tar.gz&#xff0c;canal.admin-1.1.7.tar.gz 是一个监控服务&#xff0c;可选&#xf…...

【CVE-2022-22733漏洞复现】

Apache ShardingSphere ElasticJob-UI漏洞 漏洞编号:CVE-2022-22733 文档说明 本文作者:SwBack 创作时间:2024/1/21 19:19:19 知乎:https://www.zhihu.com/people/back-88-87 CSDN:https://blog.csdn.net/qq_30817059 百度搜索: SwBack漏洞描述 Apache ShardingSphere Elast…...

Python爬虫---scrapy框架---当当网管道封装

项目结构&#xff1a; dang.py文件&#xff1a;自己创建&#xff0c;实现爬虫核心功能的文件 import scrapy from scrapy_dangdang_20240113.items import ScrapyDangdang20240113Itemclass DangSpider(scrapy.Spider):name "dang" # 名字# 如果是多页下载的话, …...

【机器学习】机器学习四大类第01课

一、机器学习四大类 有监督学习 (Supervised Learning) 有监督学习是通过已知的输入-输出对&#xff08;即标记过的训练数据&#xff09;来学习函数关系的过程。在训练阶段&#xff0c;模型会根据这些示例调整参数以尽可能准确地预测新的、未见过的数据点的输出。 实例&#x…...

下述默认构造函数有什么问题?

12.4 // points to string allocated by new // holds length of string 独立的、相同的数据,而不会重叠。由于同样的原因,必须定义赋值操作符。对于每一种情况,最终目的 都是执行深度复制,也就是说,复制实际的数据,而不仅仅是复制指向数据的指针。 对象的存储持续性为自动或…...

vite和mockjs配合使用

vite mockjs 当后端还没准备完成之前&#xff0c;前端可以使用 mock 模拟后端响应&#xff0c;提高开发效率 1、安装插件 使用 vite-plugin-mock 插件&#xff0c;配合mockjs完成项目的 mock 配置 npm install mockjs vite-plugin-mock2、vite配置插件 在 vite.config.js…...

【数据结构】常见八大排序算法总结

目录 前言 1.直接插入排序 2.希尔排序 3.选择排序 4.堆排序 5.冒泡排序 6.快速排序 6.1Hoare版本 6.2挖坑法 6.3前后指针法 6.4快速排序的递归实现 6.5快速排序的非递归实现 7.归并排序 8.计数排序&#xff08;非比较排序&#xff09; 9.补充:基数排序 10.总结…...

系统学英语 — 句法 — 常规句型

目录 文章目录 目录5 大基本句型复合句型主语从句宾语从句表语从句定语从句状语从句同位语从句补语从句 谓语句型 5 大基本句型 主谓&#xff1a;主语发出一个动作&#xff0c;例如&#xff1a;He cried.主谓宾&#xff1a;we study English.主系表&#xff1a;主语具有某些特…...

Github操作网络异常笔记

Github操作网络异常笔记 1. 源由2. 解决2.1 方案一2.2 方案二 3. 总结 1. 源由 开源技术在国内永远是“蛋疼”&#xff0c;这些"政治"问题对于追求技术的我们&#xff0c;形成无法回避的障碍。 $ git pull ssh: connect to host github.com port 22: Connection ti…...

Vue3新特性defineModel()便捷的双向绑定数据

官网介绍 传送门 配置 要求&#xff1a; 版本&#xff1a; vue > 3.4(必须&#xff01;&#xff01;&#xff01;)配置&#xff1a;vite.config.js 使用场景和案例 使用场景&#xff1a;父子组件的数据双向绑定&#xff0c;不用emit和props的繁重代码 具体案例 代码实…...

vue列表飞入效果

效果 实现代码 <template><div><button click"add">添加</button><TransitionGroup name"list" tag"ul"><div class"list-item" v-for"item in items" :key"item.id">{{ i…...

C语言·预处理详解

1. 预定义符号 C语言设置了一些预定义符号&#xff0c;可以直接使用&#xff0c;预定义符号也是在预处理期间处理的 __FILE__ 进行编译的源文件 __LINE__ 文件当前的行号 __DATE__ 文件被编译的日期 __TIME__ 文件被编译的时间 __STDC__ 如果编译器遵循ANSI C&#xff0c;…...

服务器与普通电脑的区别,普通电脑可以当作服务器用吗?

服务器在我们日常应用中非常常见&#xff0c;手机APP、手机游戏、PC游戏、小程序、网站等等都需要部署在服务器上&#xff0c;为我们提供各种计算、应用服务。服务器也是计算机的一种&#xff0c;虽然内部结构相差不大&#xff0c;但是服务器的运行速度更快、负载更高、成本更高…...

数字身份所有权:Web3时代用户数据的掌控权

随着Web3时代的来临&#xff0c;数字身份的概念正焕发出崭新的光芒。在这个数字化的时代&#xff0c;用户的个人数据变得愈加珍贵&#xff0c;而Web3则为用户带来了数字身份所有权的概念&#xff0c;重新定义了用户与个人数据之间的关系。本文将深入探讨Web3时代用户数据的掌控…...

python爬虫如何写,有哪些成功爬取的案例

编写Python爬虫时&#xff0c;常用的库包括Requests、Beautiful Soup和Scrapy。以下是三个简单的Python爬虫案例&#xff0c;分别使用Requests和Beautiful Soup&#xff0c;以及Scrapy。 1. 使用Requests和Beautiful Soup爬取网页内容&#xff1a; import requests from bs4 …...

抖音无水印内容管理工具:从数据获取到价值沉淀的完整指南

抖音无水印内容管理工具&#xff1a;从数据获取到价值沉淀的完整指南 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 你是否曾遇到这样的困境&#xff1a;精心收藏的抖音教学视频突然消失&#xff0c;重要的…...

避坑指南:GF-3 SAR数据预处理中常见的5个错误及解决方法

GF-3 SAR数据预处理实战&#xff1a;5个关键错误分析与Python解决方案 在遥感数据处理领域&#xff0c;GF-3卫星的合成孔径雷达(SAR)数据因其全天候、全天时的观测能力而备受青睐。然而&#xff0c;从原始数据到可用成果的预处理过程中&#xff0c;即便是经验丰富的工程师也常会…...

Fish Speech 1.5调参指南:温度、Top-P怎么调?一张表看懂所有参数

Fish Speech 1.5调参指南&#xff1a;温度、Top-P怎么调&#xff1f;一张表看懂所有参数 1. 为什么调参很重要&#xff1f;——从“能听”到“好听”的关键一步 你用过语音合成工具吗&#xff1f;是不是经常遇到这种情况&#xff1a;生成的语音虽然每个字都对&#xff0c;但听…...

5B00,5B01,5B02,1700,1701,1702,1704,P07清零软件G3800,TS3480 ,TS3380 ,G3000,G1810,TS9020, TS8020,TS3480

下载地址&#xff1a;链接:https://pan.baidu.com/s/1j7Nwv715wX1JL3qidnGyXA?pwd0000 提取码:0000 常见 佳能打印机 型号&#xff1a; G5080 G6080 G7080 G1810 G2810 G3810 G4810 G1800 G2800 G3800 G4800 G5010 G6010 G7010 G1010 G2010 G3010 G4010 G1000 G2000 G3000 G40…...

布隆过滤器与哈希索引:两级验证模型

在高并发、大数据量的系统中&#xff0c;快速判断一个元素是否“已经存在”是一项基础而关键的能力。无论是防止重复提交、抵御缓存穿透&#xff0c;还是实现分布式去重&#xff0c;都需要一种高效的存在性检查机制。实践中&#xff0c;布隆过滤器&#xff08;Bloom Filter&…...

别再只盯着data://协议了!详解Nginx日志文件包含漏洞的另类利用与防御

从日志污染到权限沦陷&#xff1a;Nginx文件包含漏洞的攻防全景解析 当Web服务器的日志文件成为攻击者的跳板&#xff0c;一场关于权限与防御的暗战便悄然展开。Nginx作为现代互联网基础设施的核心组件&#xff0c;其日志机制在记录访问轨迹的同时&#xff0c;也可能成为系统安…...

TranslucentTB:Windows任务栏透明化与个性化定制工具完全指南

TranslucentTB&#xff1a;Windows任务栏透明化与个性化定制工具完全指南 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB TranslucentTB是…...

HIT-哈工大软件过程与项目管理:从理论到实战的备考精要与核心脉络梳理

1. 软件过程与项目管理课程概述 哈工大软件过程与项目管理课程是软件工程专业的核心课程之一&#xff0c;旨在帮助学生掌握软件开发全生命周期的管理方法。这门课程将理论与实践紧密结合&#xff0c;涵盖了从需求分析到软件维护的完整知识体系。 作为一门典型的工科课程&#x…...

SolidWorks参数化建模实战:从规则定义到智能装配

1. 参数化设计的核心思想与实战价值 我第一次接触SolidWorks参数化建模是在设计一个多规格管道连接件时。当时客户要求在24小时内提供5种不同口径的变型设计&#xff0c;传统建模方法让我不得不复制粘贴并逐个修改尺寸&#xff0c;结果在第三次修改时漏掉了一个关键孔位&#x…...

从电影帧率到无线通信:用生活化案例理解TDMA时分多址原理

从电影帧率到交通信号灯&#xff1a;用生活化案例拆解TDMA时分多址技术 想象一下电影院里的24帧画面如何欺骗你的眼睛&#xff0c;或是十字路口的红绿灯如何指挥车流——这些日常现象背后隐藏的时序控制逻辑&#xff0c;正是无线通信中TDMA&#xff08;时分多址&#xff09;技术…...