前言

Drools是一款老牌的java规定引擎框架,早在十几年前,我刚工作的时候,曾在一家第三方领取企业工作。在外围的领取路由层面我记得就是用Drools来做的。

难能可贵的是,Drools这个我的项目在十几年后还仍旧放弃着开源和更新。

https://github.com/kiegroup/d...

而LiteFlow也是一款java规定引擎,于2020年开源。通过2年的迭代,当初性能和个性也十分棒,很适宜用在高复杂度的外围业务上,同时又能放弃业务的灵活性。

https://gitee.com/dromara/lit...

这篇文章咱们就来深刻比拟下这两款框架,都适宜用在什么样的场景,有什么异同点,以及在雷同的场景下表现力如何。

(其中Drools基于7.6.0版本,LiteFlow基于2.9.0版本)

尽管题主就是开源我的项目LiteFlow的作者,然而我这几天也深刻理解了下Drools,尽量从很主观的角度尝试去剖析。很多比对的后果都是基于理论应用后的感触。不过题主难免会带有一些主观的心理以及理解的片面性,尤其是Drools当初曾经更新到了8.X,说实话并没有应用过。所以说的不正确的中央也请斧正。

规定引擎的定义

首先我想明确下规定引擎的定义,因为很多小伙伴容易把规定引擎和流程引擎的概念混在一起。

规定引擎通常是嵌入在应用程序组件中的,实现了将业务决策从利用程序代码中分离出来,并应用预约义的语义模块编写业务决策。承受数据输出,解释业务规定,并依据业务规定做出业务决策。

简略来说就是,规定引擎次要解决易变逻辑和业务耦合的问题,规定驱动逻辑。以前我的项目内写死在代码里的逻辑用规定引擎能够提出来,随时热变更。

而流程引擎实现了将多个业务参与者之间依照某种预约义的规定进行流转,通常须要波及到角色信息。

简略来说就是,流程引擎次要解决业务在不同角色之间的流转问题,如销假流程,审批流程,往往要通过多个角色。规定驱动角色流转。

两款框架的异同点

Drools和LiteFlow都是优良的开源框架,都能把业务中的逻辑给剥离进去。并且领有本人表达式语法。

然而有所区别的是,Drools强调逻辑的片段规则化,你能够把外围易变局部写成一个规定文件,等同于原先写在java里的代码当初搬迁到了规定文件。规定文件里的代码全都是能够热变更的。

而LiteFlow是基于组件式的思维设计的,更强调组件的规则化,覆盖范围是整个业务。编排的最小单位是组件,规定文件用来串联组件间的流转。同时LiteFlow也反对片段式的代码规则化,因为LiteFlow也反对业务逻辑的脚本化。规定反对热变更。

所以评判一个规定引擎是否合格的次要因素有:

  1. 有没有灵便的规定表达式来反对
  2. 规定和Java之间是否十分不便的联动
  3. API调用是否不便,和各种场景零碎的集成如何
  4. 侵入性耦合比拟
  5. 规定的学习老本,是否容易上手
  6. 规定表达式是否有语言插件
  7. 规定是否和业务松耦合,存储于其余中央
  8. 规定的变更是否实时扭转逻辑
  9. 是否有界面状态来反对非技术人员的应用
  10. 框架的性能体现

上面就从这几个方面来细细比拟两款框架的表现力

规定表达式

Drools的规定表达式为Java量身定制的基于Charles Forgy的RETE算法的规定引擎的实现。

Drools的规定表达式贴近天然编程语言,领有本人的扩展名文件drl,语法反对全,基本上天然编程语言有的语法drl全有。所以,齐全能够把java的逻辑写在drl文件中。

来看下drl文件的大体样子:

能够看到,Drools定义规定的形式是一个规定一段,有明确的when...then,示意当满足什么条件时,做什么。在触发规定时候,会主动判断该去执行哪一段rule,如果满足多个条件,是能够触发多个规定的then的。

LiteFlow编排表达式简略易懂,底层用EL表达式语言包装而成。用于组件的流转,反对异步,抉择,条件,循环,嵌套等一些场景。

组件层面不仅能够是java组件,还能够用脚本语言来编写,目前反对了Groovy和QLExpress两种脚本语言。所有能用java实现的,用脚本语言都能够做到。

LiteFlow的规定文件大体长这个样子:

上述LiteFlow的编排表达式中,所表白的是上面一个逻辑流:

LiteFlow编排表达式反对THEN(同步),WHEN(异步),SWITCH(抉择),IF(条件),FOR(次数循环),WHILE(条件循环)等大表达式,每个表达式又有许多扩大关键字可供选用。

脚本组件反对的Groovy根本和java语法差不多,Groovy语言反对的所有你均可应用。甚至能够在Groovy语法中额定定义类和办法。

论断

总的来说,两款框架都能用脚本来定义逻辑片段,在定义逻辑片段层面,Drools应用的是自研语法,LiteFlow应用的是插件式的Groovy,其实集体感觉Groovy更靠近java语法,你甚至于能够在其中定义类和办法。Drools在高级利用中,也能够用规定定义方法,然而我感觉并不那么天然。

LiteFlow最大的特点是除了定义逻辑片段外,还能够进行全局组件的编排。而这正是LiteFlow称之为编排式规定引擎的由来。应用简略的编排语法能够设计出简单的逻辑流。反对java和脚本混编。

和Java的数据交换

在Drools的规定中,你能够通过import关键字来引入java的一些类包类进行调用。

在LiteFlow的脚本组件中,Groovy也能够通过import 来引入java的任何包来调用。

Drools中,能够间接援用到fact对象。

LiteFlow中,能够间接援用到context对象,context上下文贯通整个编排链路。

LiteFlow中,通过@ScriptBean注解,你甚至能够把spring上下文中的bean引入进来间接调用。利用这个个性,甚至于能够在脚本中调用rpc,调用数据库dao对象取数据。这个在Drools外面尽管也能够做到,然而要麻烦的多。

论断

根本都能满足和java的数据交换需要,然而LiteFlow在场景上反对的显然更加多一点。

API以及集成

在API调用层面,Drools须要去定义KieContainer,KBase,KSession一系列对象。LiteFlow框架只须要应用到LiteFlowExecutor对象。

Drools反对了编程式接入,然而在springboot中须要本人写很多配置类来去集成。

LiteFlow不仅反对了编程式接入,在springboot环境下更是提供了主动拆卸的starer接入形式,连定义LiteFlowExecutor都不须要,间接从上下文中就能够拿到主动拆卸后的对象进行调用。

论断

LiteFlow api更加简略,同Springboot集成度更加高。

侵入性耦合比拟

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");endrule "score_2"when    $order:Order(amount>=100 && amount < 500)then    $order.setScore(100);    System.out.println("触发了规定2");endrule "score_3"when    $order:Order(amount>=500 && amount < 1000)then    $order.setScore(500);    System.out.println("触发了规定3");endrule "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除了文中所提到的一些个性以外,还有很多其余各种各样的探索性的玩法和高级个性。是一款很值得深挖的框架。

官网地址: https://liteflow.yomahub.com/