前一段时间在开发了一个做文本分析的项目。
在项目技术选型的过程中, 尝试使用了 Drools规则引擎。
让它来作为项目中有关模式分析和关键词匹配的任务。
但后来,因为某种原因, 还是撇开了 Drools 。
现将这个过程中使用 Drools 的一些经验和心得记录下来。
(一)什么时候应该使用规则引擎 ~这实际是一个技术选型的问题。
但这个问题又似乎是一个很关键的问题(一旦返工的话, 你就知道这个问题是多么重要了)。
不知大家有没有过这样的经验和体会。
往往在项目开始 的时候,总会遇到应该选用什么技术?是不是应该使用最新的技术?或者应该选用什么技术 呢(PS :现在计算机软件中的各种技术层出不穷,具有类似功能的技术很多)?不管怎么样,这些问题总会困扰着我。
比如,这次的这个项目。
项目要求是要在一些 文件中(这些log 文件都是很大的应用系统所产生的,但由于legacy 的原因,log 本身的维 护和规范工作一直没有得到改善,所以想借助于一些外部应用对这些log 做以分析和清洗)抽取出有用的信息。
于是,第一个想到的就是,这是一个文本挖掘类的项目。
但又想,要抽取有用信息,必 须得建立一些规则或 pattern (模式)。
所以,我第一个想到了规则引擎。
因为这里面要建 立好多规则,而这些规则可以独立于代码级别(引擎去解析和执行。
另一个重要的原因是,我原来用过,比较熟悉。
这样,也可以节省开发 时间吧。
于是,好不犹豫的就开始做了 Demo....但事实上,在经历了一个多星期的编码、测试后,我发现运用规则引擎实在是太笨拙了。
(1)首先必须建立一些数据模型。
通过这些模型来refer 规则文件中的LHS 和Action 。
(2 )还要考虑规则的 conflict 。
如果有一些规则同时被触发,就要考虑设定规则的优先 级或者是设定activiation-group 来保证在一个group 中的规则只有一个规则可以被触发。
(3)对于 流'规则group ruleflow-group 的使用。
如果要控制在 workingmemory 中的规则被触发的顺序,则可以将这些规则分组。
然后, 通过规则建模的方式来实现。
但这也添加了一定的effort 。
修改或者更新不大方便。
~所以,基于上述体会,我更认为规则引擎更适用于那些对非流程性规则匹配的应用。
当 然,Drools 也支持对流程性规则的建模过程。
但,这也许不是最好的方式。
(二) Drools 规则引擎的使用杂记(1) Fact 的变更监听。
在Drools 里,如果一个Fact 通过规则而改变,则需将这种 改变通知给规则引擎。
这里,一般有两种方式:显式和隐式。
显式---在drl 文件中通过 up date 、modify 来通知;在程序中,通过 Fact 的引用调用 modifyObject等方法来实现。
隐式---通过在Java bea n 实现property Liste ner In terface来让引擎自动监听到属性值的变化。
我更习惯于这种方式。
因为,一般看来凡是在规则引擎中添加到 fact 都是希望引擎来帮你进行管理的。
所以,那它自己看到 fact 的变化是种很省事的办法。
也很简单,就是用Java bean property 监听的方式。
通过 StatefulSession 来注册。
调用 StatefulSession的某个 instanee 的 insert ( Object ,true )实现。
而这个 object是一个java bean 。
其中,要实现P rivate final Prop ertyCha ngeS upport cha ngesProp ertyCha ngeS upp ort( this );public void add PropertyChangeListener(final PropertyChangeListener l) { this.cha nges.add Prop ertyChangeListe ner( l );log放到一个单独的drl 文件里)并可以用规则=newthis.cha nges.fire Prop ertyCha nge ( "te mp", null,this.te mp );(2)规则触发的优先级、组设置往往,在设计我们自己的规则时, 要考虑规则的触发条件。
这不仅限于LHS 的条件部分, 还有规则本身被触发的有些设置等等。
这里,列出一些比较常用和有效的规则优先级设置方—式,以及需要注意的地方。
A. 通过Salienee 方式。
此值可正可负。
越大优先级越高,也会被引擎首先执行。
B.通过ruleflow-group 方式。
实际上,使用这种方式也就是在使用建立规则流的方式。
在Eclipse 3.3 中,Drools 提供了建立规则流的插件。
要在 两个文件(当然,插件会帮助你建立这些)。
克NewSelect a wizardWizards:|typs filter text出凸CVS□ & Dr&olsr- -O Declfibn Table;© DoiTiain Specific Language ■ 0 Guided Rule.吨 RuleFlow File■-Q Rule ProjectQ Rule Resoir 匚ee EfChpse Made ling Frameu^crkD Example EMF McMJe'l Creation VVizarcte选择 RuleFlow File 。
这里,需要注意的一点是要在启动规则引擎的时候,加入启动drl 的同级目录中建立 rf 和rfmNejit >Fl, ashCancelrule flow 的代码。
P ublic void removeProp ertyCha ngeListe nerfinal Prop ertyCha ngeListe ner I) {Inpu tStreamReader source = new Inpu tStreamReader(RuleMa nager.class.getResourceAsStream(rule_ path));P ackageBuilder builder = new P ackageBuilder(); builder.add PackageFromDrl(source);builder.addRuleFlow (new Inpu tStreamReader(RuleMa nager.class.getResourceAsStream(rule_fl ow_p ath)));Package pkg = builder.get Package 。
;RuleBase ruleBase = RuleBaseFactory. newRuleBase(); ruleBase.add Package (p kg);然后,在每次启动规则引擎的时候,调用如下方法:StatefulSessi on ss;ss.start Pro cess(flow Progress) ss.fireAllRules();这个rule flow 图中,显示了一个简单的规则流。
如RSA 就是一个rule-flow 的名字。
在这个rule set 中可以设定一组rules 。
这样,就可以分开规则执行的顺序。
在于 的另一个drl 文件中定义这些组的名字。
通过关键字ruleflow-group来表明。
C.通过activation-group 的方式。
通过这种方式,可以exclude 一组rule 中一旦有一个rule 被invoke ,而其它 rule 不会被 execute 。
同时,可以搭配使用 salienee 关键字来标明 每个rule 的优先级,这样就能够使得你想要的一般性概念的 D.在使用ruleflow-group 的时候要注意使用 lock-on-active true 关键字在每个 rule 。
这flow 的名字。
rf 和rfm 同名rule 先被匹配执行。
样可以避免一旦有rule被触发,不会造成循环匹配执行。
E.如果在LHS部分,需要调用某个方法来返回真、假值作为判断的一个条件,那么可以=用eval函数。
女0, eval(pattern.matched(5,$line.getCurrLine()))其中,pattern是某个加入到workingmemory 中的一个实例。
matched是这个实例所代表类的一个方法。
它返回boolean类型。
(3)Drools规则引擎的使用感受总之,Drools还是一个很不错的开源规则引擎。
现在v4.0以上的版本已经比以前的版本在速度上有了很大的提升。
可以作为我们一般应用程序系统的中间件产品(那些规则不是很经常改变的系统,已经非流程类规则)。
但是,这其中还是需要一些额外的effort来学习它的使用文档以及整体架构,有一定的学习曲线。
最后,我想一个较好的对于技术使用的Practice就是:首先知道它能为你做什么,它最好的应用领域,然后再去深入。
(PS:如果谁有使用Drools的问题,可以联系我!一起讨论!)题外话:Drools是规则引擎,主要是用于实现基于规则的专家系统的。
而专家系统是什么,要解决什么样的问题,可能大家不是很清楚。
所以在解决问题是,要首先有个全面的了解才行。
如果只是流程型的东西,可以考虑工作流引擎实现。
另外,对话引擎是很复杂的,涉及很多技术,NPL、推理机、知识库,甚至包含整个人工遛能领域的技术。
而其中每个技术又有不同的理论和方法,选择哪个,又如何组合这些技术也是很复杂的。
基于条件匹配方式的规则引擎必定存在一个抽象分析的过程,而且你很难控制流程式的逻辑的执行。
我们做的VisualRules也称做一个规则引擎产品,但是我们不是按照条件匹配的方式来做的。
我们是顺序执行的。
因此可以通过分支来实现决定规则执行的轨迹,甚至可以做循环类的规则。
另外可以直接在规则中操作数据库,以便于提取一些参数以及存取操作。
其实最开始我们研发这个产品时,也碰到匹配算法将规则配置变得非常难,研究挺长时间的程序员要设计规则都觉得分析的难度挺大。
不要说将来的维护人员或者业务人员。