当前位置: 首页 > 后端技术 > Java

规则引擎深度对比,LiteFlowvsDrools!

时间:2023-04-01 20:38:23 Java

前言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也支持业务逻辑的脚本化。规则支持热变更。因此,判断一个规则引擎是否合格的主要因素是:是否有灵活的规则表达式支持规则与Java的便捷联动,API调用是否方便,各种场景系统集成的侵入耦合程度如何比较规则学习成本是否好学,规则表达式是否有语言插件,规则是否可以和业务松耦合,规则是否可以存储在其他地方。逻辑可以实时更改吗?是否有支持非技术人员使用的接口形式,我们从这几个方面来详细对比一下两个框架的表现力。Drools的正则表达式是基于CharlesForgy的RETE算法为Java量身定做的规则引擎的实现。Drools的正则表达式接近自然编程语言,有自己的扩展文件drl,有完整的语法支持。基本上自然编程语言的语法drl都有了。所以,完全可以把java的逻辑写在drl文件中。看一下drl文件的大致样子:可以看到Drools定义规则的方式是一条规则,带有明确的when...then,表示满足条件时做什么。当触发一个规则时,它会自动判断应该执行哪个规则。如果满足多个条件,则可以触发多个规则。LiteFlow编排表达式简单易懂,底层用EL表达式语言封装。用于组件的流转,支持异步、选择、条件、循环、嵌套等场景。组件级别不仅可以是java组件,也可以用脚本语言编写。目前,支持两种脚本语言,Groovy和QLExpress。java能做的事,脚本语言都能做。LiteFlow的规则文件一般是这样的:上述LiteFlow排列表达式表达了如下逻辑流程:LiteFlow排列表达式支持THEN(同步)、WHEN(异步)、SWITCH(选择)、IF(条件)、FOR(时间loop)、WHILE(条件循环)等大型表达式,每个表达式都有很多扩展关键字可供选择。脚本组件所支持的Groovy与Java语法基本相似,Groovy语言所支持的一切都可以使用。甚至可以用Groovy语法额外定义类和方法。结论一般来说,这两个框架都可以使用脚本来定义逻辑片段。在定义逻辑片段层面,Drools使用自研语法,LiteFlow使用插件Groovy。其实我个人认为Groovy更接近Java的语法。您甚至可以在其中定义类和方法。Drools也可以在高级应用中使用规则来定义方法,但我觉得不是那么自然。LiteFlow最大的特点是除了可以定义逻辑片段外,还可以对全局组件进行编排。这就是LiteFlow将其称为编排规则引擎的原因。可以使用简单的编排语法来设计复杂的逻辑流。支持java和脚本混合。与Java的数据交换在Drools的规则中,可以使用import关键字引入一些Java的包类来调用。在LiteFlow的脚本组件中,也可以通过引入java的任意包来调用Groovy。在Drools中,您可以直接引用事实对象。在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,直接从上下文调用自动组装的对象即可。结论LiteFlowapi更简单,与Springboot集成度更高。侵入式耦合比较Drools需要使用KSession对象来匹配规则,其中需要在java代码中使用规则来调用。规则和java是分开的。KSession调用对象在调用级别耦合。LiteFlow的规则也是从Java中分离出来的,但是LiteFlow有组件的概念,所以需要在组件层面进行继承,但是也提供了声明式组件的选择,相对减少了声明式方法的耦合。在调用层面,同样需要调用LiteFlowExecutor对象。结论关于耦合度,由于LiteFlow提供了编排特性,API耦合度相对较高。流口水的耦合度较低。规则的学习成本Drools规则的学习成本是相当高的。由于是自研规则语法,需要非常全面的熟悉过程。而且文件都是英文的。LiteFlow的编程规则极其简单,如果不使用脚本组件,10分钟基本可以上手。即使使用groovy脚本,由于groovy和java很相似,所以学习成本很小。而且,还有大量的学习资料可以参考。LiteFlow的文档中英文都很齐全,也有很好的中文社区可以解答问题。结论在规则学习成本方面,Drools的规则学习曲线比LiteFlow高出不止一点点。有没有语言插件Drools有Eclipse和IDEA的插件,可以做语法高亮、预检和提示。LiteFlow有用于IDEA的插件来进行突出显示、预检查和提示。不在Eclipse上。结论考虑到现在用eclipse的人很少,基本上这两个规则引擎都在语言插件里面做了。规则存储Drools规则理论上支持将您的规则存储在任何地方,但这一切都需要您手动完成。自己储蓄,自己得到。Drools还有一个workbeanch插件,可以在workbeanch中存储规则。只有这个不需要自我访问。除了本地规则,LiteFlow原生支持在任何标准SQL数据库中存储规则,并恢复了对Nacos、Etcd、zookeeper等注册中心的原生支持。只需配置它。另外,还提供了扩展接口,方便自己扩展到任何存储点。结论LiteFlow的规则存储支持比Drools丰富得多。规则更改是否可以实时改变逻辑Drools热刷新规则现在看起来有点傻,它的规则是由jar生成的。然后系统远程动态读取jar包完成规则刷新。并且规则的热改必须通过工作台进行。LiteFlow在这个级别上要先进得多。如果使用Nacos、Etcd、zookeeper等存储,什么都不用做,变化会自动刷新。如果你是SQL数据库存储,或者本地存储。修改规则后,需要调用LiteFlow框架提供的API进行热修改。两种方式都可以热更新。而且在高并发下很流畅。结语LiteFlow在热更新设计上比Drools先进很多。是否有支持Drools的接口形式?Workbench是一个独立的插件包,提供web界面编写规则和事实对象。并提供检查和部署的能力。但是由于Drools主要关注的是逻辑片段,所以它不需要在布局层面提供拖放UI功能,而只是提供在界面上编写规则的能力。LiteFlow没有接口形状。目前只能使用第三方Nacos和Etcd提供的接口来辅助修改接口规则。结论Drools在UI表单生态方面领先于LiteFlow。框架性能这里用Drools和LiteFlow实现同样逻辑的Demo。根据订单金额加分的demo。这个案子的逻辑很简单。根据订单金额动态判断加多少积分:小于100元不加积分。100到500元,加100积分。500到1000元,加500积分。满1000元,加1000积分。Drools的规则如下:packagerules;importcom.example.droolsdemo.entity.Order;rule"score_1"when$order:Order(amount<100)then$order.setScore(0);System.out.println("Rule1wastriggered");endrule"score_2"when$order:Order(amount>=100&&amount<500)then$order.setScore(100);System.out.println("Rule2wastriggered");endrule"score_3"when$order:Order(amount>=500&&amount<1000)then$order.setScore(500);System.out.println("triggeredrule3");endrule"score_4"when$order:Order(amount>=1000)then$order.setScore(1000);System.out.println("Rule4istriggered");end等效的LiteFlow规则如下:=100&&金额<500){返回"b";}elseif(金额>=500&&金额<1000){返回"c";}else{返回“d”;}]]>SWITCH(w).TO(a,b,c,d);两个框架都使用脚本来编写的情况下,在测试的时候,去掉所有的打印日志,执行10万次。结果如下:Drools执行10万次,耗时0.7秒。LiteFlow全脚本组件执行10万次,耗时3.6秒。如果是脚本组件,需要安排脚本执行和脚本执行,所以耗时较长。如果LiteFlow将组件换成java再执行,结果如下:LiteFlow对所有Java组件执行10万次,耗时0.5秒结论如果LiteFlow以全脚本模式运行,比Drools耗时更长。如果它与所有java组件一起运行,它的性能可以稍微超过Drools。所以对于LiteFlow,如果你想要更高的性能,就使用java组件,如果你想要更高的灵活性,就使用脚本组件。其实在实际业务中,更推荐把易改的逻辑抽出来写成脚本组件,使用java+script混合编译。结论为什么使用Drools作为比较?首先,在题主的心目中,Drools一直是规则引擎行业的标杆。Drools有很多值得学习的概念。二是也是因为题主只熟悉Drools,其他框架都没有用好。但综合来看,作为国产规则引擎的后起之秀,LiteFlow在设计理念和支持方面明显优于Drools。编排规则引擎作为规则引擎的新方向,将继续被探索。希望大家多多支持这款国产规则引擎。在编程方向上,LiteFlow除了文中提到的一些功能外,还有很多其他的探索性玩法和进阶功能。这是一个值得深入研究的框架。官网地址:https://liteflow.yomahub.com/