规则引擎组件调研汇总

调研方向:基于开源的规则引擎框架,进行搭建集成,验证使用模式、功能支持程度、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  雪山上的蒲公英  阅读(4)  评论(0)    收藏  举报
/* 返回顶部代码 */