Drools singleton StatefulKnowledgeSession作为Web服务

bal*_*azs 5 java multithreading web-services drools

我正在使用Drools 5.6.0,我已准备好升级到6.0,因此这个问题与两个版本都相关.

我已经搜索了很多关于在多线程环境中使用Drools的内容,我仍然不确定如何继续.在下面的场景中,我试图找到一种方法,将使用大量静态事实预先初始化单例StatefulKnowledgeSession用作Web服务的业务逻辑.

我想知道下面进一步描述的场景是否有最佳实践.

  1. 我在服务器启动时创建一个StatefulKnowlegdeSession单例

  2. 初始化时,我将超过100.000个事实插入到StatefulKnowlegdeSession中.我把这些称为" 静态事实 ",因为它们不会被规则修改.静态事实更像是一组大查找表.

  3. 现在,规则引擎被放入Web服务(Tomcat)中.Web服务接收将插入到KnowledgeSession中的Request对象.在fireAllRules()之后,我希望KnowledgeSession计算一个输出对象,该输出对象将作为Web服务响应返回.

  4. 响应的计算使用静态事实.规则创建了许多临时对象,这些对象使用insertLogical()插入到工作内存中.这样可以确保在Web服务调用结束时收回原始Request对象后,将从工作内存中删除所有垃圾.

现在的问题是我将如何在多线程服务器中完成这项工作?

  • 我想尽可能只使用一个StatefulKnowledgeSession实例(单例),因为静态事实是BIG,它可能成为内存问题.

  • 不能使用在每个Web服务调用开始时新创建的StatelessKnowledgeSessions,因为插入所有静态事实将花费太长时间.

  • 我知道StatefulKnowlegdeSession不是线程安全的.此外,不再支持分区选项.

  • 但是,可以从不同的线程使用不同的WorkingMemoryEntryPoints/EntryPoints.我可以使用EntryPoints ,每个Web服务调用将使用池中的一个实例来插入Web服务请求.

这也意味着我需要使用一个特定的EntryPoint,或者至少第一个匹配Web服务请求对象的规则,将每个规则(?)相乘:

rule “entry rule for WORKER-1” // rule to be duplicated for entry points WORKER-2, WORKER-3,...
    when 
        $req : Request () from entry-point “WORKER-1”
        $stat : StaticFact( attr = $req.getAttr() )
    then
        insertLogical( new SomeTemporaryStuff ( $req ) );
end

rule “subsequent rule”
    when
        $tmp : SomeTemporaryStuff()
    then
        ...go on with the calculation and create a Response at some point...
end
Run Code Online (Sandbox Code Playgroud)

后续规则在工作内存中创建临时对象,此时如果我用几十个并发请求轰炸引擎,我真的害怕弄乱一些东西.

  • 我也可以在" fireUntilHalt "模式下启动KnowledgeSession 但在这种情况下我不知道如何从规则引擎获得同步响应以将其作为Web服务响应返回.

lau*_*une 1

我不会使用多个入口点。将请求排队到运行会话的线程。如果您想利用多核,请运行多个服务或服务线程。

对于 100k 事实,请仔细检查其字段的表示方式。String.intern() 可能可以节省大量成本。其他对象可以 - 因为它都是静态的 - 被共享。通常,在这种情况下,元素构建期间的一些额外开销在以后是有益的,例如,更少的 GC 开销。

(否则,这是一个非常好的总结,几乎是运行此场景的“指南”。+1