Drools Fusion(CEP)定义及使用方法讲解
从Drools统一行为建模平台的视野看,DroolsFusion是负责启用事件处理行为的一个模块。
定义
支持复杂事件处理,是比简单的理解事件是什么要更多得多,cep场景具有几个共同而明显的特点:
- 通常需要处理巨量的事件,但是只有少部分事件是真正关心的。
- 事件通常是不变的,因为它们是状态改变的一条记录。
- 通常有关事件的规则和查询必须是运行在被动模式(reactivemodes),即,对事件模式(patterns)的检测作出反应。
- 通常在相关的事件之间有强烈的时间关系。
- 个别事件通常是不重要的。系统关心相关事件的模式(patterns)和它们的关系
- 通常,要求系统执行组合和聚合的事件。
用fusion,要把插入drools的数据声明为事件。
drools处理数据有两种方式,云模式和流模式,默认是云模式,用fusion,需要设置为流模式。流模式,插入的数据叫事件,有时间顺序,云模式没有,
流(stream)支持
大部分CEP用例必须处理事件流(stream)。
流的特性:
- 在流中的事件通过时间戳被排序。
- 事件的数量(volumes)总是很高的。
- 原子事件自己是很少有用的。通常根据多个事件之间的相关性或流或其他来源提取含义。
- 流可以是相似的,即包含单一类型的事件;或者是异类的,即包含多种类型的事件。
声明流模式
在kmodule.xml中添加配置eventProcessingMode=“stream”为流模式
事件声明
用fusion,要把插入drools的数据声明为事件,声明事件使用@role标签
@role
把@role元数据标签指派给该事实类行
例如:
Person为javabean也就是一个事实类型
declarePerson @role(event) end
Person的属性如下:
publicclassPerson{ privateStringname; privateIntegerage; privateStringlike; privateStringsex; privateStringdesc; privateStringaddress; privateDatecreateTime; //gettersetter省略
@timestamp
每一个事件都要有一个关联的时间戳指派给它。默认时,一个给定事件的时间戳是在事件被插入到工作内存时,从SessionClock读取,并且分配给该事件。有些时候,事件用时间戳作为它自己的一个属性。在这情况下,用户可以用@timestamp标记用户属性为时间戳
例如:用Person的createTime属性为时间戳
declarePerson @role(event) @timestamp(createTime) end
@expires
重要:这个标签只有引擎运行在流(STREAM)模式之下才会被考虑.
该标签显示定义一个事件在什么时候应该到期,事件到期,事件可能不再匹配和激活任何规则时。
使用如下
@expires(1h35m)
在person例子中假设过期时间为20S
declarePerson @role(event) @timestamp(createTime) @expires(20s) end
滑动时间窗口
滑动时间窗口允许用户编写规则,其将仅匹配在最近的X时间单元内发生的事件
rule"boy" when $p:Person(age<25)overwindow:time(3s) then $p.setDesc("少年"); retract($p); end
例如:只匹配最近3秒内,年龄小于25的人
调用代码如下:
packagecom.us.fusion; importcom.us.model.Person; importorg.kie.api.KieServices; importorg.kie.api.runtime.KieContainer; importorg.kie.api.runtime.KieSession; importjava.util.Date; /** *Createdbyyangyiboon17/1/3. *@authoryangyibo */ publicclassApplication{ privatestaticKieSessiongetSession(){ KieServicesks=KieServices.Factory.get(); KieContainerkc=ks.getKieClasspathContainer(); returnkc.newKieSession("fusionAgeKS"); } publicstaticvoidrun(){ KieSessionks=getSession(); Personp1=newPerson("白展堂",2,newDate()); Personp2=newPerson("佟湘玉",7,newDate()); try{ Thread.sleep(4000); }catch(InterruptedExceptione){ System.out.println(e); } Personp3=newPerson("李大嘴",16,newDate()); ks.insert(p1); ks.insert(p2); ks.insert(p3); intcount=ks.fireAllRules(); System.out.println("总执行了"+count+"条规则------------------------------"); //ks.dispose(); } publicstaticvoidmain(String[]args){ run(); } }
规则代码如下:
packagecom.us.fusion7 importcom.us.model.Person functionvoidprintName(StringstreamName,Stringname,intage,Stringdesc){ System.out.println("streamName:"+streamName+"name:"+name+"age:"+age+"desc:"+desc); } declarePerson @role(event) @timestamp(createTime) @expires(20s) end rule"boy" when $p:Person(age>0)overwindow:time(3s) then $p.setDesc("少年"); retract($p); printName("boy",$p.getName(),$p.getAge(),$p.getDesc()); end
由于Thread.sleep(4000);所以最近3秒内只有李大嘴一条记录所以
结果如下:
streamName:boy name:李大嘴age:16desc:少年
总执行了1条规则------------------------------
范例210S内的平均年龄
滑动长度窗口
和滑动时间窗口很类似,其将仅匹配最近几次发生的事件,用法如图,只匹配最近1次发生的事件。
rule"old" when $p:Person(age>49)overwindow:length(2) then $p.setDesc("老年"); retract($p); end
例如年领大于49岁的最近两条记录
调用代码:
publicclassApplication{ privatestaticKieSessiongetSession(){ KieServicesks=KieServices.Factory.get(); KieContainerkc=ks.getKieClasspathContainer(); returnkc.newKieSession("fusionAgeKS"); } publicstaticvoidrun(){ KieSessionks=getSession(); Personp1=newPerson("白展堂",52,newDate()); Personp2=newPerson("佟湘玉",57,newDate()); try{ Thread.sleep(4000); }catch(InterruptedExceptione){ System.out.println(e); } Personp3=newPerson("李大嘴",56,newDate()); ks.insert(p1); ks.insert(p2); ks.insert(p3); intcount=ks.fireAllRules(); System.out.println("总执行了"+count+"条规则------------------------------"); ks.dispose(); } publicstaticvoidmain(String[]args){ run(); } }
规则代码
packagecom.us.fusion7 importcom.us.model.Person functionvoidprintName(StringstreamName,Stringname,intage,Stringdesc){ System.out.println("streamName:"+streamName+"name:"+name+"age:"+age+"desc:"+desc); } declarePerson @role(event) @timestamp(createTime) @expires(20s) end rule"old" when $p:Person(age>49)overwindow:length(2) then $p.setDesc("老年"); retract($p); printName("boy",$p.getName(),$p.getAge(),$p.getDesc()); end
只匹配符合规则的最近的两条记录,所以舍弃“白展堂记录”
执行结果
streamName:boy name:李大嘴age:56desc:老年
streamName:boy name:佟湘玉age:57desc:老年
总执行了2条规则------------------------------
本文所有测试例子的pom依赖
org.kie kie-api 6.5.0.Final org.drools drools-core 6.5.0.Final org.drools drools-compiler 6.5.0.Final org.drools drools-decisiontables 6.5.0.Final org.drools drools-templates 6.5.0.Final
本文所有测试例子的kmodule.xml配置
其他关键字:After,Before,During,Meet等关键字都是用于比较两个事件的发生时间顺序,用法待以后再叙
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。如果你想了解更多相关内容请查看下面相关链接