规则引擎组件调研汇总

调研方向:基于开源的规则引擎框架,进行搭建集成,验证使用模式、功能支持程度、API使用难易、及二次开发可行性等。

1.Urule

背景:由于提供页面设计功能,且开源,作为选型调研的主要目标,基于Urule开源版本改造,实现本地服务搭建,其模式为通过页面配置参数、动作及规则,业务系统实现调用。

1.1 系统架构

img

1.2 运行模式

基于一体化现状,采用分布式计算模式。即将URule部署为一个独立的Java Web应用,在这个应用里定义各个业务系统所需要业务规则,定义好后统一存储到一个规则存储仓库当中。 业务系统要使用规则时只需要指定URule Server的地址即可通过HTTP协议取到目标规则包,然后解析并运行,其运行模式图如下所示:img

1.3 页面规则设计器部分

1.3.1 库文件设计

库文件设计器包括变量库设计器、参数库设计器、常量库设计器以及动作库设计器四个部分,通过这些库文件设计器,可以将业务系统中使用的实体对象、枚举值、常量以及需要在规则中调用的Java方法映射到引擎中备用。

image-20241219104022778

其中动作库支持自定义方法实现

image-20241219111421714

1.3.2 决策集设计

image-20241219110002165

1.3.3 决策表设计

img

1.3.4 决策树设计

image-20241219110239131

1.3.5 通过知识包发布

通过页面设计规则完成之后,通过知识包的方式发布

image-20241219110434991

1.4 业务系统调用

1.4.1 集成依赖

<dependency>
    <groupId>com.sundun</groupId>
    <artifactId>edas-rule-base</artifactId>
    <version>1.0.0</version>
</dependency>

1.4.2 配置到服务端地址并调用

//创建一个KnowledgeSession对象
KnowledgeService knowledgeService = (KnowledgeService) ctx.getBean(KnowledgeService.BEAN_ID);
//映射知识包路径,匹配到对应规则
KnowledgePackage knowledgePackage = knowledgeService.getKnowledge("test/007-table");
KnowledgeSession session = KnowledgeSessionFactory.newKnowledgeSession(knowledgePackage);
//封装参数
Map<String, Object> param = new HashMap<>();
//(acc_type_code != "22" && include(seq.set('5','6','7'), pay_bus_type_code)) && create_date > "20220531"
param.put("acc_type_code", "21");
param.put("pay_bus_type_code", "1");
param.put("create_date", "20220601");
session.fireRules(param);
System.out.println(session.getParameter("result"));

1.5 使用体验

页面配置功能比较丰富,主要规则场景像规则集、决策表、决策树、评分卡都能够良好支持,也支持自定义动作的扩展。缺点是整个规则调用过度依赖页面配置了,配置规则前需在页面配好变量及动作,规则的配置也是通过页面的编辑,对应的库文件和规则在库中是二进制存储,升级需要全量替换。

2.Drools

2.1 系统架构

Drools页面配置需集成Workbench,生产环境部署不灵活,因此不作为主要选型方向,仅调研业务系统API使用。

Drools部署架构

2.2 业务系统调用

2.2.1 集成依赖

<!--添加规则引擎依赖-->
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
    <version>7.73.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-mvel</artifactId>
    <version>7.73.0.Final</version>
</dependency>

2.2.2 规则定义及配置

image-20241219112700850

image-20241219112713432

2.2.3 业务系统调用方式

// 第一步
KieServices kieServices = KieServices.Factory.get();
// 第二步
KieContainer kieContainer = kieServices.getKieClasspathContainer();
// 第三步
KieSession kieSession = kieContainer.newKieSession();
// 业务对象
Order order = new Order();
order.setAmount(100);
// 第四步
kieSession.insert(order);
// 第五步:执行规则引擎
kieSession.fireAllRules();
// 第六步:关闭session
kieSession.dispose();

System.out.println("指定规则引擎后的结果:" + order.getScore());

3.Jvs-rules

主要参考了其页面及数据库设计,由于源码不开源,不做选型。

规则设计页面

规则对应的表

4.其他内嵌式规则组件

其他组件为内嵌式,通过引入对应依赖,系统内部定义及调用其规则,方式大同小异,简要汇总如下:

4.1 EasyRules

//定义规则
Rule weatherRule3 = new RuleBuilder()
    .name("weather rule")
    .description("if it rains then take an umbrella")
    .when(fact -> fact.get("rain").equals(true))
    .then(fact -> System.out.println("It rains, take an umbrella!"))
    .build();
Rules rules = new Rules();
rules.register(weatherRule3);
//定义参数
Facts facts = new Facts();
facts.put("rain", true);
// 调用规则
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);

4.2 QLExpress

//定义规则
String qlExpress = "" +
    "if(name ==\"orderMoney\" ) {    " +
    "actual = orderMoneyHandler.doHandler(type,channelType); " +
    "} else if(name ==\"orderCount\" ) {       " +
    "actual = orderCountHandler.doHandler(type,channelType); " +
    "}" +
    "" +
    "return actual >= threshold;  ";
DefaultContext<String, Object> context = new DefaultContext<>();
//定义参数
context.put("threshold", 1000);
context.put("name", "orderMoney");
context.put("channelType", "mobile");
context.put("type", 1);
//调用规则
ExpressRunner runner = new ExpressRunner();
Object result = runner.execute(qlExpress, context,null, true, false);
System.out.println(result.toString());

4.3 Aviator

AviatorEvaluator.addFunction(new IsDiscountFunction());
//定义参数
Map<String, Object> map = new HashMap(4);
map.put("discount", new BigDecimal(0.1));
map.put("price", new BigDecimal(20.0));
map.put("limit", new BigDecimal(100.00));

//编译且执行表达式。
Object isDiscount = AviatorEvaluator.execute("isDiscount(discount,price,limit)", map);
System.out.println(isDiscount);
        
 /**
 * 自定义函数 在这里得精度计算
 */
 static class IsDiscountFunction extends AbstractFunction {
     @Override
     public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3) {
         //arg和对应的map中的value对应
         BigDecimal price = (BigDecimal) FunctionUtils.getNumberValue(arg1, env);
         BigDecimal discount = (BigDecimal) FunctionUtils.getNumberValue(arg2, env);
         BigDecimal limit = (BigDecimal) FunctionUtils.getNumberValue(arg3, env);
         //逻辑
         BigDecimal paymentAmount = price.multiply(discount);
         return AviatorBoolean.valueOf(paymentAmount.compareTo(limit) > -1 ? false : true);
     }

    @Override
    public String getName() {
        //自定义方法名称
        return "isDiscount";
    }
}

4.4 LiteFlow

LiteFlow一个编排式的规则引擎框架,组件编排,帮助解耦业务代码,让每一个业务片段都是一个组件。

利用 LiteFlow,你可以将瀑布流式的代码,转变成以组件为核心概念的代码结构,这种结构的好处是可以任意编排,组件与组件之间是解耦的,组件可以用脚本来定义,组件之间的流转全靠规则来驱动。

img

<?xml version="1.0" encoding="UTF-8"?>
<flow>
    <chain name="test_flow">
        THEN(
           prepareTrade, grantScore, sendMq, WHEN(sendEmail, sendPhone)
        );
    </chain>
</flow>

// 使用的规则文件,传递参数,上下文对象
	LiteflowResponse response = flowExecutor.execute2Resp("test_flow", flowDto, AppFLowContext.class);
	// 获取流程执行后的结果
	if (!response.isSuccess()) {
		Exception e = response.getCause();
		Log.warn(" error is {}", e.getCause(),e);
	}
	AppFlowContext context = response.getContextBean(AppFlowContext.class);
	log.info("handleApp 执行完成后 context {}",JSONObject.toJSONString(context));

其设计思想为基于组件编排,具体的规则判断和执行逻辑需要放到组件中。

5.总结

特征 Drools LiteFlow URule Boot Rule Aviator
功能特性 DRL对应规则文件,也有对应的决策表、决策流、评分卡等 除了定义逻辑片段外,还可以进行全局组件的编排,支持java和脚本混编 支持各种规则编写,决策集、决策表、决策树、决策流 普通规则、规则集、决策表 通用的脚本语言
语法规则 DRL语法也是一种DSL,上手难度还能接受,语法基本有一对一的映射 插件式的Groovy 可视化设计器,规则编写很容易 restful组装接口调用 内嵌式
易用性 开发工具集成开发环境不支持评分卡和决策树,面向开发人员;KIE环境支持多种规则编写,但可用性还是差点,需重构规则设计器 无可视化 网页版本可视化设计器简单易用,功能强大,完全面向运营人员 可视化编辑 无可视化
性能 较高 性能高 性能高 未知 性能高
规则存储 需自行实现或基于workbeanch插件 本地规则,也支持数据库及nacos 支持 内存及数据库 可抽取出规则存储数据库
热变更 需通过workbench的方式进行规则的热变更 支持 支持 支持,必须集成RabbitMQ 可通过数据库配置
运营成本 高 中,需开发人员支持 低,向导式界面编排 低 中,需开发人员支持
活跃度 活跃 活跃 开源版本基本不再更新;商用版本,每月有更新 低 活跃

基于前期调研选型特性对比,结合对应组件实际集成使用上,总结如下:

如果需要页面可视化功能,目前可选开源组件中仅有Urule支持,但其规则设计完全依赖页面,如果升级需要全量替换;对应的库文件和规则在库中是二进制存储,粒度较粗,后续基于此进行二次开发需要一定的代码改造。

如果仅需要组件的规则定义、规则执行的核心功能,大部分组件都支持,其中Aviator个人感觉支持度最好,可基于此实现相应的规则持久化存储、动作定义、调用记录等功能的扩展。

综上,可基于实际业务需求分析,如果需要可视化设计的功能,且Urule支持场景能够覆盖需求,并能接受一定的升级不灵活性,可优先选择Urule;如果倾向于灵活性,可在各内嵌式组件中选型进行二次开发;如果选择基于内嵌组件实现可视化设计功能,此项工作取决于规则拆分的粒度(例如:判断条件a>b,前后端是设计为一个条件 a>b 的粒度,还是拆分设计成左参数a、逻辑运算符>、右参数b 的粒度?),需设计确定后再行分析。

posted @ 2026-03-31 16:19  雪山上的蒲公英  阅读(144)  评论(0)    收藏  举报
/* 返回顶部代码 */