当前位置:网站首页>记一次 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
边栏推荐
- 你的站点可能还没有准备好用于Site KitSite Kit 无法访问 WordPress REST API。请确保其已在您的站点上启用。
- idea同时修改相同单词
- mininet hosts talk to real internet
- Unity插件-FairyGUI
- 图解MESI(缓存一致性协议)
- unity Domain Reload & scene Reload 静态变量重置
- LeetCode 2344. 使数组可以被整除的最少删除次数 最大公约数
- Exotic curiosity-a solution looking - bit operations
- 剑指offer:删除链表中重复的节点
- 泰伯效应的建模
猜你喜欢
随机推荐
Run ns3 with multiple processes
udp transparent proxy
光波导应用中的真实光栅效应
Optisystem应用:光电检测器灵敏度建模
Qt | 显示网络图片 QNetworkAccessManager
5款最好用的免费3D建模软件(附下载链接)
Unity插件-NGUI
The relationship between base classes and derived classes [inheritance] / polymorphism and virtual functions / [inheritance and polymorphism] abstract classes and simple factories
unity-shader(入门)
第二十九章:树的基本概念和性质
audio console无法连接到RPC服务
永久更改pip源
【进程间通信】消息队列
mininet multihomed topology
剑指offer:删除链表中重复的节点
灵活的区域定义
OpenPose 运行指令 ([email protected])
Unity中事件的3种实现方法
【无标题】
Oauth2.0 自定义响应值以及异常处理









