解决异步任务中访问ThreadLocal报错的方案及实现

使用Async如何传递ThreadLocal及自定义线程池 1. 当使用ThreadLocal存储数据时,程序中使用了@Async异步任务注解,后导致子任务中无法获取到ThreadLocal存储的数据2. 使用@Async注解后默认的线程池最大线程数和队列长度为 Integer.MAX_VALUE,当并发量增高后会导致系统负载飙升甚至系统宕机。 阅读详情

在这里插入图片描述

当开发软件程序时,我们通常需要异步记录操作日志和用户信息。操作日志可以用于跟踪系统的运行情况、查询问题以及审计目标的,而使用用户信息记录则可以用于个人化服务、权限管理和统计分析等等方面。然而,在某种情况下,我们可能会遇到以下问题:在异常任务中访问ThreadLocal的信息时报错。

问题现象和产生的原因

异步任务在不同的线路中执行,而ThreadLocal只在当前线路中可见。这意味着,当我们在异步任务中尝试访问之前在主线路或其它线路中设置的ThreadLocal变化量时,就会发生错误。这种错误可能会导致无法正确获取用户信息,并影响到日志记录的准确性和完整性。

解决方案一:转发用户信息(推荐)

为了解决异常步骤中无法访问ThreadLocal的问题,一种常见的解决方法是通过参数传递用户信息。具体而言,我们可以在登录验证通过滤器中,登录成功后将使用用户信息作为参数传递给异常步骤。这样,异步任务就可以直接使用传递的用户信息,而不依赖于ThreadLocal。

在现实过程中,我们需要在登录验证过滤器中获取用户信息,并将其传递给异常任务。可以通过在异常任务的结构制造数中接收用户信息参数的方式来现实。这样,在异步任务中就可以使用该用户信息,进行日志记录或其他相关操作。

解决方案二:使用InheritableThreadLocal

另一种解决方案是使用InheritableThreadLocal。InheritableThreadLocal代替ThreadLocal,它是ThreadLocal的一个子类,它可以在子线中继承父线中设置的信息。通过使用InheritableThreadLocal我们可以在主线中设置用户消息到ThreadLocal,然后在异常任务的子线程序中获得这些信息。

需要注意的是,使用InheritableThreadLocal可能会引入一些性能开发,并且需要小心处理线路之间的共享数据。在使用时,我们需要确保合适时机设置和清理中的价值,以防止内存泄漏或数据混乱InheritableThreadLocal等问题。

解决方案三:使用单线程的线程池

如果你希望登录过滤器和异步任务在同一个线程中执行,可以使用单线程的线程池来执行异步任务。这样,所有的异步任务都会在同一条线路中按顺序执行,保证登录通过滤器和异步任务的执行在同一条线路上。

在这种方案中,我们需要创建一个单线程的线程池,然后将异常步骤提交给该线程池执行。这样,所有的异常步骤事务都会在同一条线路中执行,可以确保登录过过滤器中设置的ThreadLocal中用户信息在异常操作执行期间可用。

需要注意的是,使用单线程的线程池可能会影响系统的并发性能,因为所有的异常步骤都在同一个线程中顺序执行。因此,该方案适合用于对并发性能要求不高的场景。

方案一详细实现步骤

这里用一个简单的demo项目演示方案一的详细解决步骤

模拟记录操作日志,在查询方法加上Log自定义注解,前端发起请求执行该方法就会执行记录操作日志。

在这里插入图片描述

1、过滤器对请求进行过滤和放行,判断session中是否有用户信息。

在这里插入图片描述
2、如果session中有用户信息则查询数据库校验用户信息,校验通过后返回用户信息。

在这里插入图片描述
3、将用户信息存入session中,下一次请求就会携带用户信息。

在这里插入图片描述
4、将用户信息存入ThreadLocal中并放行。

在这里插入图片描述
5、进入AOP方法增强代码,处理日志信息,这里可以获取到ThreadLocal信息。

在这里插入图片描述
6、处理日志信息方法也可以获取ThreadLocal信息,通过参数传递的方式将用户信息传递给异步任务方法。

在这里插入图片描述
7、进入异步任务方法,这里可以看到通过方法传参可以获取到用户信息,而使用ThreadLocal则获取不到用户信息。

在这里插入图片描述
8、执行SQL将操作日志信息写入到数据库中。

在这里插入图片描述

以上是针对该问题的几种解决方案。具体选择哪种解决方案需要根据具体的业务和需求进行相应的调整。
在这里插入图片描述

SaToken 1.37 异步线程上下文丢失:3种场景分析与2种解决方案实测 本文深入分析了SaToken 1.37在异步线程中Web上下文丢失的问题,提供了3种常见场景的详细解析和2种实测有效的解决方案。针对`@Async`异步调用、手动创建子线程和RPC调用等场景,推荐参数透传和上下文重置方案,帮助开发者有效解决`SaTokenException: 非Web上下文无法获取Request`异常。 阅读详情

相关推荐

不当使用ThreadLocal导致的错误 - 前端

为了避免可能的错误,我们应该注意在使用完ThreadLocal后进行清理操作,并在使用线程池时显式地清除ThreadLocal中的数据。例如,在Web应用程序中,当一个请求处理完毕后,对应的线程也应该结束,但线程本身可能会被线程池缓存以备重用,这时ThreadLocal中的数据就会残留下来。为了确保在多线程环境下的数据安全性,Java中的ThreadLocal类常被使用。在上面的修改后的代码中,我们添加了一个clearContext方法,该方法在使用完ThreadLocal后调用,以清除当前线程中的变量。

AvskBug的博客 254

【JUC并发编程】14 TransmittableThreadLocal解决线程池中ThreadLocal无法在父子线程之间传递的问题

TransmittableThreadLocal如何使用? 如何解决线程池中ThreadLocal无法在父子线程之间传递的问题?

健身变秃,coding变强 2597

Spring定时任务中使用ThreadLocal的坑

NULL 博文链接:https://bijian1013.iteye.com/blog/2380233

Java多线程10:ThreadLocal的作用及使用

ThreadLocal的作用 从上一篇对于ThreadLocal的分析来看,可以得出结论:ThreadLocal不是用来解决共享对象的多线程访问问题的,通过ThreadLocal的set()方法设置到线程的ThreadLocal.ThreadLocalMap里的是是线程自己要存储的对象,其他线程不需要去访问,也是访问不到的。各个线程中的ThreadLocal.ThreadLocalMap以及Th...

weixin_33836874的博客 276

Android 13 GMS认证避坑:手把手教你搞定RKP配置,解决GTS测试fail

本文详细解析Android 13 GMS认证中的RKP(远程密钥配置)全流程,提供GTS测试失败的深度解决方案。从RKP核心概念到实战配置技巧,帮助开发者规避常见陷阱,确保设备顺利通过Google安全认证,特别适合需要快速掌握Android13 GMS认证的工程师参考。

weixin_29796279的博客 464

做量化没有实时数据怎么行?我找到一个超级好用的Python库,速度还贼快!

今天咱们介绍了 pytdx 这个神奇的库,重点包括:✅ 安装 pytdx✅ 连接 TDX 服务器✅ 获取实时行情数据✅ 获取 K 线数据✅ 获取分笔成交数据总之,pytdx 是一个速度快、免费、易用的量化利器,适合 A 股量化交易的同学们使用。如果你还在为数据发愁,赶紧试试吧!🚀顺手再看就是对花姐最大的支持,期待你的关注。

奔跑的蜗牛 5724

@Async 异步任务的五个坑

本文深入剖析了Spring中@Async异步任务注解的五个常见陷阱,通过可运行的demo和真实日志展示了问题现象与解决方案。

Leighteen 246

DC综合中set_dft_signal的实战配置与优化策略

本文深入解析了DC综合中set_dft_signal命令的实战配置与优化策略。文章从命令的核心作用出发,详细拆解了-view、-type、-usage等关键参数,并通过扫描使能与时钟门控的实战案例,展示了如何正确配置以实现测试模式下的功耗优化。同时,文章总结了高级优化策略、与低功耗流程的协同方法以及常见错误排查清单,旨在帮助数字芯片设计工程师构建高可测性、低功耗的稳健DFT基础。

weixin_28347369的博客 403

《Spring 中上下文传递的那些事儿》Part 7:异步任务上下文丢失问题详解

在现代 Java 应用中,异步编程已经成为提升性能、解耦业务逻辑的重要手段。无论是使用 CompletableFuture、线程池(ExecutorService)、定时任务(ScheduledExecutorService),还是 Spring 的 @Async 注解,我们都可能遇到一个共同的问题:上下文信息丢失。 本文将带你深入理解为什么异步任务中会出现上下文丢失,并提供多种解决方案,包括手动拷贝、TTL 封装、AOP 自动注入等,帮助你在各种场景下都能正确地传递上下文。

Good good study,day day up 1568

Apifox 自动化测试新增流程控制条件,复杂测试场景不再是问题

在 if 条件后的输入框填写请求接口得到的变量 viewed ,选择条件为「小于」,输入比较数值 10 ,并在 if 条件下添加「宠物下架处理」步骤。借助新增的自动化测试流程控制条件,测试人员就可以使用 Apifox 去实现更深层更多样的测试应用场景,帮助提升测试效率,减少复杂场景的测试操作。「查询新建宠物」、「修改宠物状态为已售出」和「查询宠物状态是否修改」步骤为当前在售宠物信息盘点的三个标准步骤,所以将这三个步骤合成一组。在循环中添加「查询在售宠物」和「修改宠物状态」步骤;

877

Windows下用Anaconda安装d2l库避坑指南(附PermissionError解决方案)

本文详细介绍了在Windows系统下使用Anaconda安装d2l库的完整指南,特别针对常见的PermissionError问题提供了多种解决方案。从环境准备到库安装,再到VSCode配置和数据路径处理,帮助读者顺利搭建深度学习环境并运行《动手学深度学习》的代码示例。

3a9bq4r8t2y的博客 225

Spring 异步线程中传递ThreadLocal

ThreadLocal 的传递

keep_learn的专栏 1759

Zabbix安装与部署 系统环境:centos7.0

Zabbix安装与部署 系统环境:centos7.0

weixin_42485027的博客 2600

线程切换,线程异步,异步线程, 上下文 传递, threadLocal的处理

当代码中, 录制回放单测拦截中使用了threadLocal上下文时. 异步时就需要上下文切换. 如果做的不好,就会导致上下文未清除.上下文就乱了. 第一次是空,后面再使用到该线程时就不为空,就一直是第一次的上下文了. 除非你在finnally里清空掉.TestContext: 单测中使用的上下文 TestContext.getInstance();但是你不知道你当前的接口的后面是不是还要用TestContext.getInstance()// 执行业务逻辑.在异步线程后,肯定是会报错的.

fei33423的专栏 680

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Spring Boot异步任务里RequestContextHolder为啥拿不到request?一个参数就搞定

本文深入解析了Spring Boot异步任务中RequestContextHolder无法获取request对象的原因,并提供了通过设置`setRequestAttributes`的第二个参数`true`来启用InheritableThreadLocal的解决方案。文章详细探讨了ThreadLocal的线程隔离特性、解决方案的适用场景与限制,以及与其他异步组件的整合方法,帮助开发者高效处理异步任务中的request对象访问问题。

weixin_30906185的博客 337

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Feign异步远程调用丢失请求头的两种解决方法

4、由代码可知,请求信息是从requestAttributesHolder 中获取的,而 requestAttributesHolder 类型为 ThreadLocal,即本地线程。异步任务直接使用线程池里的线程去执行方法,而不是继续使用原有线程,导致无法继续使用原线程中的数据。5-2-1、ThreadLocal 的子类 InheritableThreadLocal 可以使让子线程继承父线程的信息。5-2-2、因此,可以通过语句,在异步调用前将父线程中的请求信息绑定给子线程。

m0_51614605的博客 1337

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

AsnycLocal与ThreadLocal

【代码】AsnycLocal与ThreadLocal。

极客神殿 853

Spring Boot 异步线程间数据传递的优雅实现

日常开发都使用ThreadLocal来存取用户信息等全局遍历,但是当遇到了多线程,ThreadLocal就失效了,以下提供2种方法帮助我们优雅实现线程间的数据传递。

qq_22918201的博客 551

慎用 @Async:从 ThreadLocal 失效到 Cookie 丢失的连环坑

摘要: 线上导出接口因@Async异步调用导致Cookie丢失,触发文件中心鉴权失败。问题根源在于异步线程无法继承主线程的HttpServletRequest上下文,且请求对象在主线程结束后失效。解决方案包括:提取必要参数(如Cookie)而非传递Request、使用InheritableThreadLocal传递上下文,或重构逻辑避免跨服务异步调用。此外,@Async还存在异常处理黑洞(需实现AsyncUncaughtExceptionHandler)、事务失效(需分离异步与事务方法)及线程池耗尽(需自定

dom_jun的博客 905

Spring Security异步无法获取用户认证信息

InheritableThreadLocal可以获取到子线程信息‌,主要是因为它是ThreadLocal的一个子类,设计用来在父子线程间传递数据。具体来说,当父线程创建一个子线程时,这通常涉及到在子线程的Thread对象中复制父线程的ThreadLocalMap,从而使子线程能够访问到父线程中设置的变量。需要注意的是,虽然InheritableThreadLocal提供了在子线程中访问父线程数据的能力,但它并不适用于所有情况,然而,在某些情况下,我们需要父线程中的数据能够在由父线程创建的子线程中被访问,

rt5476238的博客 1471

包装CompletableFuture的异步任务让其开启事务(加入主线程事务不可取)

核心问题:事务的ACID特性与多线程资源共享存在本质冲突Session/Connection非线程安全数据库连接和JPA Session设计为单线程使用多线程同时操作同一连接会导致SQL执行顺序混乱、状态覆盖操作原子性无法保证看似"都完成"实际是假象,存在数据竞争风险一个线程的操作可能被另一个线程覆盖,且不会抛出异常违反事务"要么全完成,要么全不完成"的基本原则隔离级别失效多线程并发修改使数据库隔离机制形同虚设脏读、不可重复读、幻读问题无法避免。

qq_64000191的博客 746

Java日志追踪实战:MDC原理、配置与异步场景解决方案

在分布式系统和微服务架构中,日志追踪是提升系统可观测性的关键技术。其核心原理是通过线程绑定的上下文容器,为每个请求关联唯一标识,实现日志的串联与聚合。这项技术的核心价值在于能够显著提升问题排查效率,支持链路追踪和日志分析。在实际应用场景中,它广泛用于Web请求处理、异步任务执行和微服务间调用。本文聚焦于SLF4J MDC(映射诊断上下文)的实现,详细解析其基于ThreadLocal的设计,并通过日志框架集成、Spring Boot实战配置,特别是针对异步场景下MDC传递的解决方案,如使用TaskDecora

weixin_34224941的博客 405

使用 transmittable-thread-local 组件解决 ThreadLocal 父子线程数据传递问题

在某个项目中,需要使用mybatis-plus多租户功能以便数据隔离,前端将租户id传到后端,后端通过拦截器将该租户id设置到ThreadLocal以便后续使用,代码大体上如下所示: ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<>(); threadLocal.set(1); 我在Controller层使用线程池取了租户id,代码大体上如下所示: ExecutorService executorServ

狂盗一枝梅的专栏 2229

Feign配置RequestContextHolder.getRequestAttributes()为null的解决方案

Feign配置RequestContextHolder.getRequestAttributes报NullPointException问题出现场景分析原因关于RequestContextHolder原因解决方案 问题出现场景 feign配置如下 异步代码中调用feign 当用在异步代码中用feign调用微服务时,后台日志中出现报错信息NullPoinntException 分析原因 关于RequestContextHolder 实现原理 ThreadLocal ThreadLocal是一个本地线程副本变

07feng的博客 8056
上一篇: SpringBoot整合RabbitMQ实现RPC远程调用功能
下一篇: Python基础学习笔记
霁晨晨晨
博客等级 码龄4年 359粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霁晨晨晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值