从 6.4.0 升级到 8.44.2 后,流口水会出现内存不足的情况

问题描述 投票:0回答:1

我们正在将 Drools Fusion 应用程序从 6.4.0 升级到 8.44.2。该应用程序仅管理 1 个在流模式下长时间运行的 KieSession (config.setOption(EventProcessingOption.STREAM))。事件被插入到在 fireUntilHalt() 中运行的会话中。

在 6.4.0 中,同一会话可能会运行数天或数周。当我们仅仅依靠事件的自动驱逐(根据我们的配置,在 24 小时后)时,我们经历过事件可能会极端爆发并导致内存不足问题。因此,我们添加了一些额外的逻辑,在事件插入之前检查会话中已存在的事件不超过 N 个。如果发生这种情况,我们将选择 20% 最旧的事件并手动从会话中删除相关事实(使用如下代码,ep 是入口点,Event 是我们的应用程序域事件类)。

for (Event e : toDelete) {
    FactHandle fh = ep.getFactHandle(e);
    if (fh != null) {
        ep.delete(fh);
    }
}

相同的代码现在可以在 8.44.2 上运行,但据我们所知,内存消耗正在缓慢但稳定地增加。手动删除逻辑似乎仍然有效,我们看到相关的日志条目。但会话在某些时候会走向 OOM。内存直方图看起来像这样

enter image description here

在该测试设置中,我们始终检查事件数量是否保持在 11'000 以下。如果达到此级别,则将从会话中删除最旧的 2000 个。尽管如此,活跃事件的数量似乎仍在增加。大多数内存似乎都保存在 TruthMaintenanceSystemRuleTerminalNodeLeftTuple 类中。

我必须承认,我不知道这个类的用途是什么,也不知道为什么它的实例显然被“永远”保留。知道这里会发生什么吗?

heap-memory drools complex-event-processing
1个回答
0
投票

因为您正在处理入口点以获取事实句柄并从中删除,您能否确认您是从正确的入口点删除的?您真的是指 drl 中的入口点(因为会话也实现了入口点)吗?为什么在第 3 行有一个条件来处理在工作内存中找不到对象的情况,这是预期的(业务逻辑的一部分)还是您只是隐藏了错误的删除逻辑(从错误的入口点删除)?

1 for (Event e : toDelete) {
2     FactHandle fh = ep.getFactHandle(e);
3     if (fh != null) {
4         ep.delete(fh);
5     }
6 }

您能否尝试其他删除方式,而不是依赖 drools 工作内存之外的代码来跟踪对象(并存储对它们的引用)?

global AtomicLong maxCount

rule "maxCount"
    salience -1
when
    $new: CountedModel()
    not CountedModel(ordinal > $new.ordinal)
    $old: CountedModel()
    not CountedModel(ordinal < $old.ordinal)
then
    if ($new.ordinal - $old.ordinal >= maxCount.get()) {
        delete($old);
    }
end
© www.soinside.com 2019 - 2024. All rights reserved.