Drools从6.4.0升级至8.44.2后出现内存溢出问题求助
问题分析:Drools Fusion 8.44.2升级后内存泄漏(TruthMaintenanceSystemRuleTerminalNodeLeftTuple占用)
背景信息
- 版本变更:从Drools Fusion 6.4.0升级至8.44.2
- 运行模式:流模式(
config.setOption(EventProcessingOption.STREAM)),单实例长期运行的KieSession,通过fireUntilHalt()持续处理插入事件 - 6.4.0版本表现:可稳定运行数天甚至数周;曾因突发大量事件仅依赖24小时自动驱逐机制导致OOM,因此新增前置校验逻辑:插入事件前检查会话内事件数,若超过阈值N则删除最旧的20%事件,代码如下:
for (Event e : toDelete) { FactHandle fh = ep.getFactHandle(e); if (fh != null) { ep.delete(fh); } }
升级后异常现象
- 内存缓慢但持续增长,手动删除逻辑日志显示执行正常,但会话最终仍触发OOM
- 内存直方图显示:大部分内存被
TruthMaintenanceSystemRuleTerminalNodeLeftTuple类实例占用
原因解析
类作用说明
TruthMaintenanceSystemRuleTerminalNodeLeftTuple是Drools中**真值维护系统(TMS)**的核心组件之一,用于跟踪规则匹配过程中生成的元组数据,维护事实间的依赖关系,确保规则触发的正确性与一致性。简单来说,它是规则引擎记录“哪些事实匹配了哪些规则条件”的中间数据载体。
实例无法回收的可能原因
- TMS逻辑版本变更:从6.4.0到8.44.2,Drools的TMS实现有较大迭代。旧版本中删除事件时,TMS会自动清理关联的元组实例;但新版本可能存在逻辑遗漏,手动删除事件后,TMS未同步清理对应的
LeftTuple,导致这些元组持有已删除事件的引用,无法被GC回收。 - 手动删除的不完整性:当前删除逻辑仅针对事件本身,但流模式下Drools会为事件生成大量中间匹配元组(包括
TruthMaintenanceSystemRuleTerminalNodeLeftTuple)。这些元组可能关联到已删除事件的隐式引用,而手动删除操作未触发规则引擎对这类元组的清理流程。 - 长期会话的元组累积:使用
fireUntilHalt()的长期会话中,8.x版本为提升规则执行性能,调整了元组的生命周期管理策略,可能延长了元组的持有时间;若未配置合理的元组过期或清理机制,会导致实例不断累积。而6.4.0版本的TMS清理策略更激进,不会出现这类问题。
排查与修复建议
- 调整TMS相关配置:检查Drools 8.x新增的元组清理、缓存过期参数,尝试设置元组过期时间,强制触发旧元组的回收
- 替换手动删除逻辑:改用Drools官方推荐的事件驱逐机制,比如
@Expire注解或配置EntryPoint的过期策略,确保事件删除时触发TMS的完整清理流程 - 启用调试日志:开启Drools TMS模块的调试日志,跟踪元组的创建与清理过程,定位未被清理的元组关联关系
- 补充清理动作:在手动删除事件后,调用
kieSession.flush()触发规则引擎的状态同步,确保关联元组被正确处理
内容的提问来源于stack exchange,提问作者jammann
相关产品推荐
相关产品推荐

