无状态知识会话和有状态知识会话有什么区别。我阅读了一些文档都保持状态。但是我什么时候可以使用无状态/有状态知识会话。
8 回答
无状态:事实/工作记忆在触发规则之前被插入到知识库会话中。这些事实可以通过在执行规则时调用对象上的公共方法来设置,并且在设置这些对象后返回更改的值。
执行规则时事实的任何变化,例如insert(xyz)
或modify(xyz)
,都不会被规则引擎知道。
有状态的:事实/工作内存在触发规则之前插入到知识库会话中,并且在触发规则之后必须调用 dispose() 以避免内存泄漏。
执行规则时事实的任何变化,例如insert(xyz)
或modify(xyz)
,都会被规则引擎知晓。
无状态意味着为每个请求创建一个新会话(因此不维护任何状态)。有状态意味着它将从上一个命令结束时会话的任何状态继续(例如,插入到会话中的所有数据仍然存在)。
我看到它的基本区别是会话在无状态下自动处理的方式。选择一个与另一个没有性能增益。实际上,无状态会话在其背后使用有状态会话。所以去图吧!
我想在这里引用 drools 文档,这让我头脑清醒。
“StatelessKnowledgeSession 提供了一个方便的 API,包装了 StatefulKnowledgeSession。它避免了调用 dispose() 的需要。无状态会话不支持迭代调用,调用 execute(...) 的行为是一个单一的方法,它将在内部实例化 StatefulKnowledgeSession,添加所有用户数据并执行用户命令,调用 fireAllRules,然后调用 dispose()。”
所以基本上,无状态会话是一次使用的有状态会话。
这意味着无状态会话也可以进行推理,这与许多文档和这里的一些答案不同!这应该只取决于规则的“then”部分,无论您是否使用“modify”。
虽然我自己没有验证这一点,但这篇文章似乎支持了我的推理。
https://groups.google.com/forum/#!topic/drools-usage/qYbqiS1ht4g
在有状态的会话中,我们可以修改事实并重新插入它们,即使之前已经触发了规则。
另一方面,在无状态会话中,一旦所有规则都被触发( using execute()
),我们就无法进一步修改事实并将它们重新插入会话中(因为会话在execution()
被调用后不可用)。
1) 在无状态知识会话的情况下,当规则执行时,即一旦调用 fireRules 方法,插入的事实(在 then 部分)中的修改对规则引擎是不可用的。在有状态知识会话的情况下,事实的任何变化都可用于规则引擎。
2) 一旦规则被触发,Stateful Knowledge Session 对象必须调用方法 dispose() 来释放会话并避免内存泄漏。
3) 在有状态知识会话的情况下,对事实的任何更改都可用于规则引擎。所以规则被迭代地调用。如果在 DRL 的最后一条规则中修改了 Fact A,则此更改将重新激活所有规则并触发基于 Fact A 构建的规则。无状态知识会话并非如此。
隐藏的事实是无状态会话在其背后使用有状态会话
这个链接是准确的:https: //groups.google.com/forum/#!topic/drools-usage/ qYbqiS1ht4g Drools 应该在官方文档中添加。
有状态:“插入的数据对象将成为工作内存的一部分,以后可以重用以进一步执行规则。”
无状态:“规则执行后,插入的数据对象不会存储在工作内存中”。
如果我参考关于 Stateless Session 的 Drools 文档,它会说:
无状态 KIE 会话是不使用推理对事实进行迭代更改的会话。在无状态 KIE 会话中,来自先前KIE 会话调用(先前会话状态)的数据在会话调用之间被丢弃,而在有状态 KIE 会话中,该数据被保留
这可能需要在文档中进行澄清,并且iterative将替换为interactive。
这并不意味着:
执行规则时对事实的任何更改,例如 insert(xyz) 或 modify(xyz),都不会被规则引擎知道。
正如@Prakhyat 在他的评论中所建议的那样。
实际上,您可以告诉 Drools 忽略对工作内存所做的任何更新(插入/修改),以获得更好的性能,使用Phreak 中的顺序模式以获得更好的性能:
在顺序模式下,Drools 引擎会忽略规则中的任何插入、修改或更新语句,并以单个顺序执行规则。因此,在顺序模式下规则执行可能会更快,但重要的更新可能不会应用于您的规则。
顺序模式仅适用于无状态 KIE 会话
[...]
Drools 引擎默认禁用顺序模式。