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

多线程如何使用MDC传递上下文信息

关于利用MDC来实现上下文请求链路追踪,具体可以看我之前写的博客上下文追踪
由于MDC内部使用的是ThreadLocal来在线程中传递上下文信息的,但是我们往往会在代码中使用异步操作,这个时候,父线程的ThreadLocal信息是无法传递给子线程的(阿里开源的inheritableThreadLocal)。这个时候需要用到线程池的装饰器来解决这个问题。
RpcContext和httpHeader都可以用这个装饰器解决多线程传递问题。

public class MdcTaskDecorator implements TaskDecorator {
    @Override
    public Runnable decorate(Runnable runnable) {
        Map<String, String> contextMap = MDC.getCopyOfContextMap();
        RequestAttributes context = RequestContextHolder.currentRequestAttributes();
        return () -> {
            try {
                // Right now: @Async thread context !
                // (Restore the Web thread context's MDC data)
                if (contextMap != null) {
                    MDC.setContextMap(contextMap);
                }
                if (context != null){
                    RequestContextHolder.setRequestAttributes(context);
                }
                runnable.run();
            } finally {
                MDC.clear();
            }
        };
    }
}

然后在你的异步线程池配置文件中加上装饰器。我用的是Spring集合的@Async来实现异步的,加装饰器的代码如下:

@Configuration
public class AsyncConfig extends AsyncConfigurerSupport {

    @Bean("asyncExecutor")
    public ThreadPoolTaskExecutor asyncExecutor() {
        ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(30);
        threadPool.setMaxPoolSize(500);
        threadPool.setWaitForTasksToCompleteOnShutdown(true);
        threadPool.setAwaitTerminationSeconds(60 * 15);
        threadPool.setThreadFactory(
            new ThreadFactoryBuilder().setNameFormat("async-thread-pool-%d").build());
            //指定装饰器
        threadPool.setTaskDecorator(new MdcTaskDecorator());
        return threadPool;
    }

    @Override
    public Executor getAsyncExecutor() {
        return asyncExecutor();
    }
}

相关文章:

  • HAproxy+Nginx7层负载均衡
  • 算法竞赛进阶指南 货仓选址
  • 报告分享|OpenMediation:2022年年中全球手游市场报告
  • docker容器中elasticsearch配置跨域访问(elasticsearch-head插件访问不到es集群)
  • Echarts 的使用
  • Docker安装部署(详细版)
  • 【react hook】umi获取虚拟dom元素 并点击按钮滚动到对应元素位置
  • list深度拷贝转为JSON字符串,放到Redis
  • java计算机毕业设计社区老人健康服务跟踪系统源码+系统+数据库+lw文档+mybatis+运行部署
  • LeetCode_309_最佳买卖股票时机含冷冻期
  • Vue中使用lottie动画加载json文件
  • 炒股加杠杆方式有哪些
  • 23届秋招前端笔面经合辑(持续更新)
  • Docker实时查看日志命令
  • CSS 实现内阴影的方法
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • 《深入 React 技术栈》
  • CentOS7 安装JDK
  • ES6 学习笔记(一)let,const和解构赋值
  • Java 内存分配及垃圾回收机制初探
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • Redis 中的布隆过滤器
  • SOFAMosn配置模型
  • 测试开发系类之接口自动化测试
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 聚类分析——Kmeans
  • 深度学习入门:10门免费线上课程推荐
  • 使用 QuickBI 搭建酷炫可视化分析
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 用quicker-worker.js轻松跑一个大数据遍历
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • #宝哥教你#查看jquery绑定的事件函数
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (Git) gitignore基础使用
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .htaccess配置重写url引擎
  • .NET Core WebAPI中封装Swagger配置
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .net6使用Sejil可视化日志
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • [04] Android逐帧动画(一)
  • [100天算法】-实现 strStr()(day 52)
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大
  • [Android] 修改设备访问权限
  • [Angular 基础] - 数据绑定(databinding)
  • [bzoj1006]: [HNOI2008]神奇的国度(最大势算法)
  • [BZOJ1040][P2607][ZJOI2008]骑士[树形DP+基环树]
  • [codeforces] 25E Test || hash
  • [hdu2196]Computer树的直径