当前位置:网站首页>记一次 ThreadLocal 泄漏导致的 shardingsphere-jdbc-core 单元测试偶发失败的排查与修复
记一次 ThreadLocal 泄漏导致的 shardingsphere-jdbc-core 单元测试偶发失败的排查与修复
2022-08-02 14:14:00 【[email prote】
文章目录
现象
https://github.com/apache/shardingsphere/issues/19346
本地运行 shardingsphere-jdbc-core 的单元测试没问题,但 GitHub Actions 中的 CI 有一定概率失败。
排查过程
尝试本地复现
尝试 Maven 运行单个模块的测试
使用 Maven 构建 shardingsphere-jdbc-core,多次尝试未能复现:
mvn clean install -pl shardingsphere-jdbc/shardingsphere-jdbc-core
尝试使用不同 JDK 运行模块的测试
尝试了以下几种 JDK:
- Oracle Java 17.0.1
- Eclipse Temurin 17.0.1
- Docker Official OpenJDK 17.0.1
均未能复现问题。
分析问题
分析日志
重新观察报错信息:
可以发现几乎所有的报错都指向同一个地方:
都是因为 TransactionType 是一个 Mock 的对象,导致获取不到 ShardingSphereTransactionManager。
TransactionType 的来源?
来源一:
TransactionRule 的 defaultType
来源二:
来源于 TransactionTypeHolder。但 TransactionTypeHolder 中的值的根本来源是 TransactionRule 的 defaultType。所以根源还是来源一。
TransactionTypeHolder 使用了 ThreadLocal 存储 TransactionType。由于单元测试在同一个模块中默认单线程串行运行,所以此处考虑有没有可能是单元测试中存在 ThreadLocal 泄漏?
由于报错的直接原因是 TransactionType 是个 mock 对象,因此我们先看看哪里有可能会产生 mock 的 TransactionType。
通过全局搜索发现,代码中并没有直接 mock TransactionType。但是存在不少 TransactionRule 的 RETURNS_DEEP_STUBS。
很可能是这些 TransactionRule 的 DEEP_STUBS 返回的 mock 的 TransactionType。
通过在 TransactionTypeHolder 打断点也能确认,部分单元测试会将 mock TransactionType 放入 ThreadLocal
再次尝试本地复现
但是本地如何才能重现问题证明泄漏?
分析测试执行顺序
根据经验,单元测试偶发报错很大可能和执行顺序有关系,观察 GitHub Actions 报错的单元测试执行顺序:
发现其中的 org.apache.shardingsphere.driver.jdbc.adapter.ConnectionAdapterTest 使用了 mock TransactionRule 并且在报错的测试之前执行:
相关链接:https://github.com/apache/shardingsphere/runs/7407025246?check_suite_focus=true
但是本地执行单元测试时,ConnectionAdapterTest 永远在会报错的测试后面,通过 Pattern 指定也无法控制执行顺序。
想办法调整单元测试执行顺序
换个思路,如果我们把 ConnectionAdapterTest 测试类挪个位置?
在本地把 ConnectionAdapterTest 挪到 org.apache.shardingsphere.driver.jdbc.core.statement 包下面:
再次执行测试,本地复现成功:
修复方案
单元测试中凡是涉及 mock TransactionRule DEEP_STUBS 的地方都需要清理 ThreadLocal。
https://github.com/apache/shardingsphere/pull/19362
如何避免?
与 mockStatic 泄漏不同,使用 ThreadLocal 的是生产代码,对于不熟悉代码的人根本不知道里面使用了 ThreadLocal,更不知道会有泄漏的风险。最好的解决方案是从生产代码上避免使用 ThreadLocal,但需要考虑实际情况。
版权声明
本文为[[email protected]]所创,转载请带上原文链接,感谢
https://blog.csdn.net/wu_weijie/article/details/126059089
边栏推荐
猜你喜欢
随机推荐
在mininet中测试arp欺骗
嵌入式学习硬件篇------初识ARM
第三十三章:图的基本概念与性质
Manifest merger failed : Attribute [email protected] value=
shader入门精要1
C语言函数调用过程-汇编分析
Litestar 4D – WebCatalog 7:全自动数据管理
Qt | 串口通信 QSerialPort
如何编辑VirtualLab Fusion结果的格式
EastWave应用:光场与石墨烯和特异介质相互作用的研究
Unity-Ads广告插件
tpproxy-tcp透明代理
idea同时修改相同单词
Oauth2.0 补充
【线程】 理解线程(并行)线程同步的处理(信号量,互斥锁,读写锁,条件变量)
shader 和 ray marching
关于推荐系统的随想
unity Domain Reload & scene Reload 静态变量重置
Windows下mysql服务无法启动:服务没有报告任何错误。
计算机网络中的安全(一)网络安全的概念与加密原理