当前位置:网站首页>小心 transmittable-thread-local 的这个坑
小心 transmittable-thread-local 的这个坑
2022-07-30 11:25:00 【InfoQ】
异常现场
-javaagent:/path/to/transmittable-thread-local-2.12.1.jar
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor' available: expected single matching bean but found 3: executor1,executor2,executor3
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1200)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:420)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1127)
……
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
……
AbstractApplicationContext.getBean
ThreadPoolTaskExecutor
NoUniqueBeanDefinitionException
排查问题
public static void doSth(Object subtag, Object extra, long time) {
ApplicationContextContainer.getBean(ThreadPoolTaskExecutor.class)
.execute(() -> {
// 一些业务代码
});
}
@Component
public class ApplicationContextContainer implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextContainer.applicationContext = applicationContext;
}
}
applicationContext.getBean
ThreadPoolTaskExecutor
@Configuration
public class ExecutorConfig {
@Bean(value = "executor1")
public Executor executor1() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// 一些初始化方法
taskExecutor.initialize();
return taskExecutor;
}
@Bean(value = "executor2")
public Executor executor2() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// 一些初始化方法
taskExecutor.initialize();
return TtlExecutors.getTtlExecutor(taskExecutor);
}
@Bean(value = "executor3")
public Executor executor3() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// 一些初始化方法
taskExecutor.initialize();
return TtlExecutors.getTtlExecutor(taskExecutor);
}
}
Executor
ThreadPoolTaskExecutor
TtlExecutors.getTtlExecutor
ThreadPoolTaskExecutor
TtlExecutors.getTtlExecutor
public static Executor getTtlExecutor(@Nullable Executor executor) {
if (TtlAgent.isTtlAgentLoaded() || null == executor || executor instanceof TtlEnhanced) {
return executor;
}
return new ExecutorTtlWrapper(executor, true);
}
TtlExecutors.getTtlExecutor
ThreadPoolTaskExecutor
if
- 代码没改,之前好好地,怎么就报错了;
- 本地好使,为什么放在服务器上就报错了。
定位问题
TtlExecutors.getTtlExecutor
if
- TtlAgent.isTtlAgentLoaded():这个是判断 ttlAgentLoaded 标识,这个后文再说;
- null == executor:输入参数为 null,显然不符合;
- executor instanceof TtlEnhanced:输入参数是
TtlEnhanced
类型,输入的是ThreadPoolTaskExecutor
类型,不符合。
public static boolean isTtlAgentLoaded() {
return ttlAgentLoaded;
}
ttlAgentLoaded
public final class TtlAgent {
public static void premain(final String agentArgs, @NonNull final Instrumentation inst) {
kvs = splitCommaColonStringToKV(agentArgs);
Logger.setLoggerImplType(getLogImplTypeFromAgentArgs(kvs));
final Logger logger = Logger.getLogger(TtlAgent.class);
try {
logger.info("[TtlAgent.premain] begin, agentArgs: " + agentArgs + ", Instrumentation: " + inst);
final boolean disableInheritableForThreadPool = isDisableInheritableForThreadPool();
// 省略非相关代码
ttlAgentLoaded = true;
} catch (Exception e) {
String msg = "Fail to load TtlAgent , cause: " + e.toString();
logger.log(Level.SEVERE, msg, e);
throw new IllegalStateException(msg, e);
}
}
// 省略非相关代码
}
premain
ExecutorConfig
ThreadPoolTaskExecutor
ExecutorTtlWrapper
applicationContext.getBean(clazz)
-javaagent:/path/to/transmittable-thread-local-2.12.1.jar
transmittable-thread-local
ExecutorConfig
ThreadPoolTaskExecutor
applicationContext.getBean(clazz)
ThreadPoolTaskExecutor
NoUniqueBeanDefinitionException
-javaagent:/path/to/transmittable-thread-local-2.12.1.jar
解决问题
applicationContext.getBean(beanName, clazz)
public static void doSth(Object subtag, Object extra, long time) {
ApplicationContextContainer.getBean("executor1", ThreadPoolTaskExecutor.class)
.execute(() -> {
// 一些业务代码
});
}
边栏推荐
- GBJ2510-ASEMI电机专用25A整流桥GBJ2510
- TensorFlow自定义训练函数
- 基于时延估计的扰动卡尔曼滤波器外力估计
- Scheduling of combined electric-heating system based on multi-objective two-stage stochastic programming method
- 牛客-TOP101-BM42
- Underwater target detection method based on spatial feature selection
- 2022-07-29 Gu Yujia Study Notes Exception Handling
- Taobao/Tmall taobao comments q&a list interface API
- 柔性机械系统分布参数建模及其控制的研究与进展
- 定制.NET 6.0的依赖注入
猜你喜欢
Apifox 生成接口文档 教程与操作步骤
The battle-hardened programmer was also deceived by a fake programmer from a certain fish. The trust between programmers should be the highest, and he alone destroyed this sense of trust
LeetCode_236_Last Common Ancestor of a Binary Tree
VSCode更改插件的安装位置
反转链表-递归反转法
Typroa 替代工具marktext
单片机工程师笔试题目归纳汇总
Redis master-slave replication
基于MySQL数据库,Redis缓存,MQ消息中间件,ES搜索引擎的高可用方案解析
Verilog语法基础HDL Bits训练 07
随机推荐
不用if分支对同一个变量做判断的方法
Database transactions, JDBC operations and data types
How to add data to the request header when feign is called remotely
RY-D1/1 Voltage Relay
ansible学习笔记01
win下怎么搭建php环境的方法教程
Explain the problem of change exchange in simple terms - the shell of the backpack problem
Leetcode 125. 验证回文串
电压继电器HDY-A/1-220VAC-1
spin lock和mutex使用场景的差异
The battle-hardened programmer was also deceived by a fake programmer from a certain fish. The trust between programmers should be the highest, and he alone destroyed this sense of trust
Microsoft SQL服务器被黑客入侵 带宽被窃取
Verilog语法基础HDL Bits训练 08
LeetCode_235_Last Common Ancestor of Binary Search Tree
360闷声干大事获赞无数,数字安全如何保障?还得看企业安全云
Horizontal comparison of 5 commonly used registration centers, whether it is used for interviews or technical selection, is very helpful
向上管理读书笔记
基于滑模控制的不确定中立型系统有限时间稳定
《跟唐老师学习云网络》 - 问题定位 - 主机通但容器不通
Verilog grammar basics HDL Bits training 08