基于 Drools 计时器的规则会话始终驻留在内存中并导致内存泄漏
Drools timer based rule session always resides in memory and cause memory leak
我是 Drools 的新手。我想在触发规则后延迟 5 秒(并且只延迟一次)。所以,我使用 timer(int:5s) 来做到这一点。但是我发现规则执行后,我的控制台应用程序永远不会终止,它的 javaw.exe 进程仍然存在于我的任务管理器中。唯一的方法是调用 ksession.dispose()。但这是不可接受的,因为在我们的集群架构师中很难找到这个 ksession。
那么,有没有办法让ksession在规则执行后自动销毁?
这是我的简单测试用例:
主要class
public class App {
public static void main( String[] args ) {
System.out.println("Started...");
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(new ClassPathResource("Timer.drl", App.class), ResourceType.DRL);
KnowledgeBase kbase = kbuilder.newKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
ksession.fireAllRules();
System.out.println("Ended");
}
}
drl 文件
package myDrools.TimerTest1
rule "Your First Rule"
timer(int:5s)
when
eval(true)
then
System.out.println("Finished");
end
输出将是:
Started...
Ended
Finished
但我的控制台应用程序永远不会终止。有什么不对?我在 Drools 5.6.0 Final 和 6.4.0 Final 中都对其进行了测试。但是,他们两个都有同样的问题。我认为 ksession 应该被处理掉,因为 timer(int:5s) 不是间隔计时器。
计时器 运行 与托管会话的线程并行并使会话保持活动状态。在某种程度上,它们旨在用于 运行 不确定的会话,即未开始调用 fireAllRules。
以下情况应该可以让您完全关机:
rule "Your First Rule"
timer( int:5s )
when
then
System.out.println("Finished");
drools.halt();
end
你的会话是这样开始的:
kieSession.fireUntilHalt();
System.out.println( "return from fireUntilHalt" );
kieSession.dispose();
编辑
如果您在任何情况下都需要调用 halt,您可以添加另一个具有否定条件的规则,该规则会立即调用 halt。
rule "stop if not met"
when
// negated condition X
then
drools.halt();
end
提示:否定条件X是不是not X
!
根据 laune 的出色回答,我修改了我的 drl 文件以确保 drools.halt() 将始终被命中。 (注意:v6.4.0 Final 是可以的。但是 v5.6.0 Final 会为 do 子句抛出异常)
dialect "mvel"
rule "Hello World"
timer(int:5s)
when
m : Message()
if ( m.status == Message.HELLO)
do[hello]
then
System.out.println( "other status" );
drools.halt();
then[hello]
System.out.println( "Hello!" );
drools.halt();
结束
我是 Drools 的新手。我想在触发规则后延迟 5 秒(并且只延迟一次)。所以,我使用 timer(int:5s) 来做到这一点。但是我发现规则执行后,我的控制台应用程序永远不会终止,它的 javaw.exe 进程仍然存在于我的任务管理器中。唯一的方法是调用 ksession.dispose()。但这是不可接受的,因为在我们的集群架构师中很难找到这个 ksession。
那么,有没有办法让ksession在规则执行后自动销毁?
这是我的简单测试用例:
主要class
public class App { public static void main( String[] args ) { System.out.println("Started..."); KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add(new ClassPathResource("Timer.drl", App.class), ResourceType.DRL); KnowledgeBase kbase = kbuilder.newKnowledgeBase(); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); System.out.println("Ended"); } }
drl 文件
package myDrools.TimerTest1 rule "Your First Rule" timer(int:5s) when eval(true) then System.out.println("Finished"); end
输出将是:
Started... Ended Finished
但我的控制台应用程序永远不会终止。有什么不对?我在 Drools 5.6.0 Final 和 6.4.0 Final 中都对其进行了测试。但是,他们两个都有同样的问题。我认为 ksession 应该被处理掉,因为 timer(int:5s) 不是间隔计时器。
计时器 运行 与托管会话的线程并行并使会话保持活动状态。在某种程度上,它们旨在用于 运行 不确定的会话,即未开始调用 fireAllRules。
以下情况应该可以让您完全关机:
rule "Your First Rule"
timer( int:5s )
when
then
System.out.println("Finished");
drools.halt();
end
你的会话是这样开始的:
kieSession.fireUntilHalt();
System.out.println( "return from fireUntilHalt" );
kieSession.dispose();
编辑
如果您在任何情况下都需要调用 halt,您可以添加另一个具有否定条件的规则,该规则会立即调用 halt。
rule "stop if not met"
when
// negated condition X
then
drools.halt();
end
提示:否定条件X是不是not X
!
根据 laune 的出色回答,我修改了我的 drl 文件以确保 drools.halt() 将始终被命中。 (注意:v6.4.0 Final 是可以的。但是 v5.6.0 Final 会为 do 子句抛出异常)
dialect "mvel"
rule "Hello World"
timer(int:5s)
when
m : Message()
if ( m.status == Message.HELLO)
do[hello]
then
System.out.println( "other status" );
drools.halt();
then[hello]
System.out.println( "Hello!" );
drools.halt();
结束