侵入性耦合比较
Drools需要在java代码里需要用到规则的地方用KSession对象去匹配规则进行调用。规则和java是分离的。在调用层面耦合了KSession调用对象。
LiteFlow的规则和java也是分离的,但是LiteFlow多了组件这一概念,所以在组件层面是需要继承的,但是同时也提供声明式组件的选择,使用声明式的方式耦合相对要减少一些。在调用层面也需要去调用LiteFlowExecutor对象。
「结论」
在耦合度上面,由于LiteFlow提供编排特性,API耦合度相对稍高一些。Drools耦合少一些。
规则的学习成本
Drools的规则学习成本挺高的。由于是自研的规则语法,需要一个很全面的熟悉过程。而且文档全英文。
LiteFlow的编排规则极其简单,如果你不使用脚本组件的话,基本上10分钟即可上手。就算使用了groovy脚本,由于groovy非常类似于java,学习成本也非常少。况且有大量的学习资料可以参阅。
LiteFlow的文档中英文齐全,还有良好的中文社区可以答疑解惑。
结论
在规则学习成本上,Drools的规则学习曲线比LiteFlow高出不止一丁点。
是否有语言插件
Drools在Eclipse和IDEA上均有插件来做语法的高亮,预检查和提示。
LiteFlow在IDEA上有插件来做高亮,预检查和提示。Eclipse上没有。
结论
考虑到使用eclipse的人几乎很少了,基本上2款规则引擎在语言插件上都做到了。
规则的存储
Drools的规则理论上支持你的规则存于任何地方,但这一切都需要你手动去额外完成。自己去存,自己去取。
Drools还有款workbeanch的插件,可以将规则存于workbeanch中。只有这个是不需要自己存取的。
LiteFlow除了本地规则以外,原生支持将规则存储于任何标准SQL的数据库,还原生支持了Nacos,Etcd,zookeeper等注册中心。只需要配置一下即可。除此之外,还提供了扩展接口,方便你自己扩展成任意的存储点。
「结论」
LiteFlow的规则存储支持比Drools丰富的多。
规则的变更能否实时改变逻辑
Drools热刷新规则的方式现在看起来有点傻,它的规则是通过生成jar的方式。然后系统远程动态读取jar包来完成规则刷新的。
而且一定得通过workbench的方式进行规则的热变更。
LiteFlow在这个层面做的高级很多。如果你是用Nacos,Etcd,zookeeper等方式存储,不用做任何事,改变即自动刷新。如果你是SQL数据库存储,或者本地存储。在改变规则之后,需要调用LiteFlow框架提供的一个API进行热变更。2种方式均可热更新。并且在高并发情况下是平滑的。
「结论」
LiteFlow在热更新设计层面比Drools先进很多。
是否有界面形态来支持
Drools有workbench,workbench是一个独立的插件包,提供了web界面编写规则以及fact对象。并提供了检查和部署的能力。但因为Drools主要关心逻辑片段,并不需要提供编排层面的拖拽UI功能,只是提供了在界面上编写规则的能力。
LiteFlow并没有界面形态。目前只能通过第三方的Nacos,Etcd提供的界面来辅助完成界面的规则修改。
「结论」
Drools在UI形态生态上领先LiteFlow一截。
框架的性能表现
这里用Drools和LiteFlow实现了同样的一段逻辑Demo。
根据订单金额来加积分的Demo案例。
案例逻辑很简单,根据订单的金额来动态判断该加多少积分:
小于100元,不加积分。
100到500元,加100积分。
500到1000元,加500积分。
1000元以上,加1000积分。
其中Drools的规则如下:
package rules; import com.example.droolsdemo.entity.Order; rule "score_1" when $order:Order(amount<100) then $order.setScore(0); System.out.println("触发了规则1"); end rule "score_2" when $order:Order(amount>=100 && amount < 500) then $order.setScore(100); System.out.println("触发了规则2"); end rule "score_3" when $order:Order(amount>=500 && amount < 1000) then $order.setScore(500); System.out.println("触发了规则3"); end rule "score_4" when $order:Order(amount>=1000) then $order.setScore(1000); System.out.println("触发了规则4"); end
其中等价的LiteFlow规则如下:
<?xml version="1.0" encoding="UTF-8"?> <flow> <nodes> <node id="w" type="switch_script"> <![CDATA[ def amount = defaultContext.getData("order").getAmount(); if (amount < 100){ return "a"; }else if(amount >= 100 && amount < 500){ return "b"; }else if(amount >= 500 && amount < 1000){ return "c"; }else{ return "d"; } ]]> </node> <node id="a" type="script"> <![CDATA[ def order = defaultContext.getData("order"); order.setScore(0); println("执行规则a"); ]]> </node> <node id="b" type="script"> <![CDATA[ def order = defaultContext.getData("order"); order.setScore(100); println("执行规则b"); ]]> </node> <node id="c" type="script"> <![CDATA[ def order = defaultContext.getData("order"); order.setScore(500); println("执行规则c"); ]]> </node> <node id="d" type="script"> <![CDATA[ def order = defaultContext.getData("order"); order.setScore(1000); println("执行规则d"); ]]> </node> </nodes> <chain name="chain1"> SWITCH(w).TO(a, b, c, d); </chain> </flow>
两款框架都全用脚本来写的情况下,测试的过程中,去除所有的打印日志,执行10w次,得到的结果如下:
Drools 执行10w次,耗时0.7秒
LiteFlow全脚本组件执行10w次,耗时3.6秒
由于LiteFlow在全脚本组件的情况下,需要做脚本的执行和编排脚本的执行,所以花费的时间更长。
如果LiteFlow把组件更换成java,再进行执行,得到的结果如下:
LiteFlow 全Java组件执行10w次,耗时0.5秒
结论
如果LiteFlow采用全脚本的方式运行,耗时会比Drools更长。如果采用全java组件的方式运行,其性能能超越Drools一点。
所以对于LiteFlow而言,如果你希望更高的性能,则采用java组件,如果你希望更高的灵活性,则采用脚本组件。
其实在实际业务中,把容易更改的逻辑抽出来写成脚本组件,采用java+脚本混编的方式,是更为推荐的做法。
结语
为什么会拿Drools来作为比较,其一在题主心中,Drools一直是规则引擎界的标杆,drools有很多理念非常值得学习。其二也是因为题主也只熟悉Drools,其他的框架没有很好的使用过的缘故。
但是综合来看,作为国产规则引擎后起之秀LiteFlow显然在设计理念,支持度方面是要优于Drools的。编排式规则引擎作为规则引擎的一个新的方向,也会一直探索下去的。希望大家能多多支持这款国产的规则引擎。在编排方向,LiteFlow除了文中所提到的一些特性以外,还有很多其他各种各样的探索性的玩法和高级特性。是一款很值得深挖的框架。