Rete算法是Charles Forgy在1979年的论文中首次提出的针对基于规则的知识表示的模式匹配算法。 目前,大多数规则引擎仍以rete算法为中心,但已改进,包括drool、个性化睫毛等。 介绍rete算法的概念、一些术语和使用规则引擎应注意的问题。
我们先来看看下面的公式。
(Off This-production )
LHS /* one or more conditions */
--
RHS /* one or more actions */
)
薄生产是一个规则,是一系列的lhs (提升侧)条件,而RHS (右手侧)是我们满足条件后应该执行的动作。
结合这张图介绍一些概念:
产品内存(pm )由所有产品组成。
工作内存(WM )是外部输入基于匹配算法形成的,反映正在运行的规则引擎的状态,记录各种数据。 WM中的每个item被称为工作存储器(wme ),并且是由外部输入生成的。
agenda负责匹配、冲突解决和采取行动。
rete是internet的意思(拉丁语),它最终解释(或编译)所有规则,生成包括alpha网络、rete网络在内的识别网络。 alpha网络是基于LHS生成的网络,根据外部输入快速识别condition是否成立,并与该beta网络进行交互以更新网络的整体状态,如下图所示。
基本的alpha网络如上图所示,当所有的condition都被parse到这样的网络上,从外部输入wme时,该wme进入这样的网络进行识别,到了底部,condition就成立了当然,这个网络是最容易实现的,实际的规则引擎需要提供更快的算法来识别输入的wme整个alpha网络是巨大的字符串匹配和过滤网络,在大量condition的情况下更快各种规则引擎的实现又不一致。 例如,个性化的睫毛如下图所示。
(defrule done )
(测试)
(number? number )
(TEST IS DONE )
(INIT CREDIT 5)
(客户代理? age )
(has? 类型' PP ' )
=
(资产(测试完成) )
这是在解释此production后生成的网络。 现在让我们先关注红色节点。 这些节点是阿尔法网络的节点。 这张图只是说明了大致的过程。 以第一列为例,第一个红色节点指示输入是否与字符串TESTING匹配,第二个节点指示输入是否与TESTING后面的参数(slot )匹配。 如果我们的资产测试进入WM,则此fact将匹配规则done中的第一个condition。 其他可以按顺序类推。 值得注意的是最后的condition,has是我们定制的function。 这样的功能,没有单独生成个性睫毛age这一列的最后一个节点。 这样的condition具有以下特征:需要运行代码来确定某个事实是否成立。 这段代码不仅具有字符串匹配,还具有实时性。 开发这样的condition需要注意。 因为alpha network在运行时会多次执行此condition是否成立,这取决于匹配算法的特性,所以需要使用cache和规则语言的特性来避免不必要的code的执行,提高性能。
让我们贴一个更复杂的例子:
图太大了,断不了一个。
让我们来看两个关于beta网络的例子。 当alpha网络被过滤并建立condition,WME传递到beta网络时,绿色节点起作用。 该节点是连接节点,有两个输入、一个连接节点和一个alpha node (红色)。第一个连接节点称为左输入适配器。 如果节点为空,则图中的黄色节点首先将此节点称为左输入
join node就只包含了一个WME,下一个join node则包含了两个WME,以此类推。图中天蓝色的node上方的join node 完全匹配了production执行需要的condition,所以这个rule就被激活等待执行了。
假设我们需要编辑业务逻辑,那么最好的描述载体就是流程图,简单的流程图包含以下一些基本单元:起始节点,逻辑判断,执行动作,结束节点。这些节点可以完成最简单的业务逻辑描述,那么我们把这些流程parse到规则的时候,我们会怎么去做,第一个逻辑判断单元返回true,于是我们执行某个动作,第二,三个逻辑判断单元返回true我们执行某个动作,相当于会parse到两个规则,符合condition1,production1触发,符合condition2,3,production2触发,有了beta网络,我们在触发production2时只需要判断condition2,3是否成立,对于更复杂的情况,beta网络提高了速度,避免了重复匹配。
开发中使用规则引擎也遇到些问题,总结如下:
1)规则引擎中对于特殊condition的处理,由于condition会在部分production中重复出现,所以会造成condition的重复匹配问题,影响了程序的性能,这个要结合项目去优化rule脚本的parse或者使用cache去提升性能。
2)内存消耗问题,rete算法是空间换时间,所以对于内存的消耗是比较大的,特别是加载rule的时候(生成网络),在运行期内存会缓慢增长,所以gc效率需要注意,同时单个服务器所能承受的压力(多个WM)也跟规则引擎息息相关。
3)测试,对于使用规则去表达业务的系统,如何测试是必须解决的问题,对于这个问题,也只能保证基本的流程分支覆盖测试,对于复杂情况下的defect很难发现,不过有些原则需要注意,如果要使用规则引擎,我们必须完全以规则引擎为核心,对于业务逻辑必须尽可能的抽取到规则引擎去实现,对于扩展实现的function粒度必须小且简单,不要再代码中去实现业务逻辑。
4)大部分的condition需要是不变的,也就是说基本信息需要保持稳定不变。比如某客户公司上属集团信用额度大于100w这样的condition,这个额度变化的频度不会很高,不需要去实时匹配。
5),remove WME production是较复杂的操作,规则较复杂时,应该尽量少去做这样的操作。