Drools入门
目录
- Drools简述
- Drools架构
- Rate算法
- 在IDEA中构建一个DEMO
- 规则动态更新
- 生产环境中使用Drools需要考虑的问题
Drools简述
- 规则引擎
drools是一个开源的规则引擎。世界上本没有路,走的人多了就有路了。JAVA一开始也没有设计模式,但经过各种个样的需求和场景开发,工程师总结了常用场景抽象程设计模式。
规则引擎也是各种不同的需求场景中总结得出的。一般在系统设计之初会通过代码直接实现一些业务需求,比如用户连续签到3天就送一张优惠券。随着产品不断的发展就会出现一些差异不大的需求,比如将上周送5块钱的优惠券改为10块,显然我们要抽象类似场景做一个通用的功能减少重复工作,同时让业务规则和数据解耦。
同时规则引擎也是一个专家系统。何为专家系统?简单来说就是专业人员使用的系统,比如系统的运营人员。规则引擎对没有开发能力的人员进行赋能,让专业的人做专业的事。 - 常见的规则引擎
- IBM的iLog,商业产品
- Drools,开源
- 最近比较火的FLink CEP,开源
- Easy Rule,开源
- 阿里的qlexpress,开源
架构
-
KIE(Knowledge Is Everything) 知识就是一切。kie是一个提供业务的自动化和管理的解决方案项目集合
-
Drools engine
左边是规则,右边是事实(数据)。中间就是执行器(决策引擎)
Rete算法
Rete在拉丁文中译为“net”,Rete算法是利用网络筛选对规则匹配进行优化的算法实现。其核心思想是将分离的匹配项根据内容动态构造匹配树,以达到显著降低计算量的效果
在IDEA中构建一个DEMO
- maven依赖
<properties>
<drools.version>7.5.0.Final</drools.version>
</properties>
<dependencies>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.version}</version>
</dependency>
</dependencies>
- 目录要求
- kmodule.xml
<?xml version="1.0" encoding="utf-8" ?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="rules">
<ksession name="all-rules"></ksession>
</kbase>
</kmodule>
- test.drl
package com.naixuan.rules
import com.naixuan.Applicant;
import com.naixuan.Action;
rule "Is of valid age"
when
$a: Applicant(age < 18)
then
$a.setValid(false);
new Action("执行动作").doSomeThing();//执行动作方式一
insert(new Action("不合法"));//执行动作方式二
end
rule "send_act"
when
$a: Action()
then
$a.doSomeThing();
end
- 代码
public class App {
public static void main(String[] args) {
KieServices kieServices = KieServices.Factory.get();
//默认自动加载 META-INF/kmodule.xml
KieContainer kieContainer = kieServices.getKieClasspathContainer();
//kmodule.xml 中定义的 ksession name
KieSession kieSession = kieContainer.newKieSession("all-rules");
Applicant applicant = new Applicant("Mr John Smith", 17);
kieSession.insert(applicant);
kieSession.fireAllRules();
kieSession.dispose();
}
}
public class Applicant {
private String name;
private int age;
private boolean valid;
public Applicant(String name, int age) {
this.name = name;
this.age = age;
this.valid = true;
}
//getter/setter
}
public class Action {
private String msg;
public Action(String msg) {
this.msg = msg;
}
public void doSomeThing() {
System.out.println(msg);
}
}
- 运行结果
执行动作
不合法
规则动态更新
- 加载
import org.kie.api.KieServices;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieBuilder;
KieServices ks = KieServices.Factory.get();
KieFileSystem kfs = ks.newKieFileSystem()
kfs.write("src/main/resources/KBase1/ruleSet1.drl", stringContainingAValidDRL)
.write("src/main/resources/dtable.xls",
kieServices.getResources().newInputStreamResource(dtableFileStream));
KieBuilder kieBuilder = ks.newKieBuilder( kfs );
// Enable executable model
kieBuilder.buildAll(ExecutableModelProject.class)
assertEquals(0, kieBuilder.getResults().getMessages(Message.Level.ERROR).size());
- 更新
import org.kie.api.KieServices;
import org.kie.api.builder.ReleaseId;
import org.kie.api.runtime.KieContainer;
import org.kie.api.builder.KieScanner;
...
KieServices kieServices = KieServices.Factory.get();
ReleaseId releaseId = kieServices
.newReleaseId("com.sample", "my-app", "1.0-SNAPSHOT");
KieContainer kContainer = kieServices.newKieContainer(releaseId);
KieScanner kScanner = kieServices.newKieScanner(kContainer);
// Start KIE scanner for polling the Maven repository every 10 seconds (10000 ms)
kScanner.start(10000L);
生产环境中使用Drools需要考虑的问题
- 规则匹配完全依赖内存,Rete算法也使用空间换时间的方式提高效率,需要评估服务容量
- 必须要实现规则动态更新
- DSL对非开发同学,也不是很友好