现在的位置: 首页 > 综合 > 正文

事件处理&时空推理(event processing/temporal reasoning)-jboss Drools Fusion

2013年05月21日 ⁄ 综合 ⁄ 共 11054字 ⁄ 字号 评论关闭

事件处理&时空推理(event processing/temporal reasoning)

概念:

下面来看看jboss的Drools Fusion
Fusion 是业务逻辑集成平台(Business Logic Integration Platform)一部分,是一个CEP/ESP引擎。 
事件,是指在应用程序域中有意义状态改变的记录 
一个复杂事件是简单事件的集合。CEP(Complex Event Processing) 处理复杂事件-从事件云中检测并选择事件,根据选择的事件和他们建立的关系发现他们的关系推理出新的数据。 
比如,一系列的巨额提款激发可疑交易事件的发生。一个复杂事件的发生是由一系列简单事件的引导形成的。 
ESP(Event Stream Processing) 是更实时(real-time)的大量事件处理。例如,根据时间计算实时平均交易量。 
一、事件(Events). 
从drools视图来看,事件就是一个特殊的事实(fact)。我们说,所有的事件都是事实,但是所有的事实并不都是事件。 
1.事件和事实不同特征: 
(1)通常不可变:事件是在应用程序域中状态改变的记录,记录已经发生的事情,可变的事件是没有意义的。 
应用程序允许给没有赋值的事件属性赋值,但是已经赋值的属性是不应该被改变的。 
(2)强时间约束:规则涉及的事件通常需要多个事件的相互关系,尤其某个事件相对其他事件发生的时间点的时间关系。 
(3)可管理的生命周期:由于上两个事件特征的原因,事件通常在一个有限的时间窗(Time Window)匹配事件和事实, 
这就让引擎管理事件的生命周期成为可能。一个事件插入working memory,引擎有能力发现一个不在匹配 
其他事实的事件,然后自动回收它,释放相关的资源。 
(4)滑动窗( sliding windows)的使用:由于所有的事件都有关联的时间戳,可以定义并使用滑动窗,让事件在特定的一段时间有效。 

2.事件声明: 

import some.package.StockTick 

declare StockTick 
    @role( event ) 
end 

将一个已有的StockTick(类)事实生命为事件类型 
@role 元数据接受2个值: 
fact:默认值,声明为常规的事实 
event:声明为事件 

由于Drools支持在DRL中声明一个事实,可以去掉StockTick(类),还可以这样: 
declare StockTick 
    @role( event ) 

    datetime : java.util.Date 
    symbol : String 
    price : double 
end 

3.事件元数据 
所有的事件都有一个事件元数据集合。当事件插入working memory,事件元数据会自动赋予默认值,我们可以用元数据标签改变他们的默认值。 
假设我们有这样的一个实体类: 
/** 
* A class that represents a voice call in 
* a Telecom domain model 
*/ 
public class VoiceCall { 
    private String originNumber; 
    private String destinationNumber; 
    private Date    callDateTime; 
    private long    callDuration;          // in milliseconds 

    // constructors, getters and setters 

(1) @timestamp 
默认的,当事件插入working memory,会读取(会话时钟)Session Clock的timestamp赋值给事件的startTimestamp。 
@timestamp( <attributeName> ) //以毫秒计算 

表示把事件的attributeName属性值赋给事件元数据startTimestamp 
declare VoiceCall 
    @role( event ) 
    @timestamp( callDateTime ) 
end 

(2) @duration 
Drools支持时间点(point-in-time)事件和时间间隔(interval-based)事件,一个时间点事件可以理解为时间间隔为0。默认,所有的事件的持续时间(duration)为0.我们可以通过@duration标签来修改事件的duration属性值。 
@duration( <attributeName> )// 以毫秒计算。 
表示把事件的attributeName属性值赋给事件元数据duration 
declare VoiceCall 
    @role( event ) 
    @timestamp( callDateTime ) 
end 

(3)@expires 
这个标签在引擎为Stream模式下才有效。默认的,当一个事件不在匹配(match)事实,激活规则(有活化的规则),事件自动失效(回收). 
@expires( <timeOffset> ) 
显示的定义事件的失效时间。 
timeOffset可以是下列形式: 
[#d][#h][#m][#s][#[ms]] 
[]表示是可选参数 

declare VoiceCall 
    @role( event ) 
    @timestamp( callDateTime ) 
    @duration( callDuration ) 
    @expires( 1h35m ) 
end 

VoiceCall事件在1小时35分钟后过期。 

二、会话时钟(Session Clock) 
Drools 5提供2种时钟。默认的是基于系统时间的即时时钟(real time clock)。另一个是虚拟(pseudo clock)时钟,可以手动控制。 
1. 即时时钟(Real Time Clock) 
虽然Drools默认使用即时时钟,我们仍然可以显示的配置: 
KnowledgeSessionConfiguration config = KnowledgeBaseFactory.newKnowledgeSessionConfiguration(); 
config.setOption( ClockTypeOption.get("realtime") ); 
2. 配置虚拟时钟(Pseudo Clock) 
KnowledgeSessionConfiguration config = KnowledgeBaseFactory.newKnowledgeSessionConfiguration(); 
config.setOption( ClockTypeOption.get("pseudo") ); 
怎样控制虚拟时钟的例子: 

KnowledgeSessionConfiguration conf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration(); 
conf.setOption( ClockTypeOption.get( "pseudo" ) ); 
StatefulKnowledgeSession session = kbase.newStatefulKnowledgeSession( conf, null ); 
        
SessionPseudoClock clock = session.getSessionClock(); 

// then, while inserting facts, advance the clock as necessary: 
FactHandle handle1 = session.insert( tick1 ); 
clock.advanceTime( 10, TimeUnit.SECONDS ); 
FactHandle handle2 = session.insert( tick2 ); 
clock.advanceTime( 30, TimeUnit.SECONDS ); 
FactHandle handle3 = session.insert( tick3 ); 

新的SessionPseudoClock时间值为0毫秒,new Date(0) 为GMT 1970 年 1 月 1 日 00:00:00 , 
clock.advanceTime( 10, TimeUnit.SECONDS ); SessionPseudoClock时间值+10秒。

三、Entry Points 
一个entry point是事实(facts)或者事件(events)进入引擎的入口点。 
1.声明Entry Points 
rule "authorize withdraw" 
when 
    WithdrawRequest( $ai : accountId, $am : amount ) from entry-point "ATM Stream" 
    CheckingAccount( accountId == $ai, balance > $am ) 
then 
    // authorize withdraw 
end 
只有账户的余额大于提款请求的金额,规则才被激活 
2.使用Entry Points 

// create your rulebase and your session as usual 
StatefulKnowledgeSession session = ... 

// get a reference to the entry point 
WorkingMemoryEntryPoint atmStream = session.getWorkingMemoryEntryPoint( "ATM Stream" ); 

// and start inserting your facts into the entry point 
atmStream.insert( aWithdrawRequest ); 

通常情况下,我们不需要硬编码把事实插入到WorkingMemory中,通过Drools pipeline, 
将从JMS或者 其他非java对象的数据源 中获得信息(对象)插入到WorkingMemory。 

默认的entry point是"DEFAULT",是事实进入WorkingMemory的入口点。 

session.insert(fact)实际上是session.getWorkingMemoryEntryPoint("DEFAULT").insert(fact)。 

四、时间推理(Temporal Reasoning) 

Drools 实现了由Allen定义的13种时间操作运算 

━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
Temporal Operators ┃         Illustration       ┃   Interpretation 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃    ___x___                 ┃                          
   x before y       ┃               ___y___      ┃ X发生在y之前 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃    ___y___                 ┃                   
   x after y       ┃               ___x___      ┃ X发生在y之后 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃      ___x___               ┃                   
   x meets y        ┃             ___y___        ┃ x结束时y开始 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃      ___y___               ┃                   
   x metby y        ┃             ___x___        ┃ y结束时x开始 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃   ______x______            ┃                   
   x overlaps y     ┃        ______y______       ┃ x开始在y之前,结束在y之后 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃        ______x______       ┃                   
x overlappedby y   ┃   ______y______            ┃ x开始在y之后,结束在y之前 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃      ___x___               ┃                   
   x starts y       ┃      ______y______         ┃ x和y同时开始,结束在y之前 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃      ______x______         ┃                   
   x startedby y   ┃      ___y___               ┃ x和y同时开始,结束在y之后 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃          ___x___           ┃                   
   x during y       ┃       ______y______        ┃ x发生在y期间 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃      ______x______         ┃                   
   x includes y     ┃         ___y___            ┃ y发生在x期间 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃             ___x___        ┃                   
   x finishes y     ┃       ______y______        ┃X开始在y之后,同y一起结束 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃       ______x______        ┃                   
   x finishedby y   ┃             ___y___        ┃X开始在y之前,同y一起结束 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
                    ┃       ______x______        ┃                   
   x coincides y    ┃             y              ┃ X和y同时发生 
━━━━━━━━━━┃━━━━━━━━━━━━━━┃━━━━━━━━━━━━━ 
1.before 

$eventA : EventA( this before[ 3m30s, 4m ] $eventB ) 
也就是: 
3m30s <= $eventB.startTimestamp - $eventA.endTimeStamp <= 4m 

before操作符的时间间隔距离是可选的: 
如果2个值都被定义了,间隔开始于第1个值,结束于第2个值。 
如果只有1个值被定义,间隔开始于该值,结束于正无穷大。 
如果没有值定义,间隔开始于1毫秒,结束于正无穷大。 

时间间隔距离也可以是负数的,例: 
$eventA : EventA( this before[ -3m30s, -2m ] $eventB ) 

注意:当时间间隔第1个值大于第2个值时,引擎会自动的调换他们。 

2.After 

$eventA : EventA( this after[ 3m30s, 4m ] $eventB ) 
也就是: 
3m30s <= $eventA.startTimestamp - $eventB.endTimeStamp <= 4m 

after操作符的时间间隔距离是可选的: 
如果2个值都被定义了,间隔开始于第1个值,结束于第2个值。 
如果只有1个值被定义,间隔开始于该值,结束于正无穷大。 
如果没有值定义,间隔开始于1毫秒,结束于正无穷大。 

时间间隔距离也可以是负数的,例: 
$eventA : EventA( this after[ -3m30s, -2m ] $eventB ) 

注意:当时间间隔第1个值大于第2个值时,引擎会自动的调换他们。 

3.meets 

$eventA : EventA( this meets $eventB ) 
也就是: 
abs( $eventB.startTimestamp - $eventA.endTimestamp ) == 0 

meets操作符有1个可选参数 

$eventA : EventA( this meets[ 5s ] $eventB ) 
也就是: 
abs( $eventB.startTimestamp - $eventA.endTimestamp) <= 5s 

注意:时间间隔不能为负 

4.metby 

$eventA : EventA( this metby $eventB ) 
也就是: 
abs( $eventA.startTimestamp - $eventB.endTimestamp ) == 0 

metby操作符有1个可选参数 

$eventA : EventA( this metby[ 5s ] $eventB ) 
也就是: 
abs( $eventA.startTimestamp - $eventB.endTimestamp) <= 5s 

注意:时间间隔不能为负 

5.overlaps 

$eventA : EventA( this overlaps $eventB ) 
也就是: 
$eventA.startTimestamp < $eventB.startTimestamp < $eventA.endTimestamp < $eventB.endTimestamp 

overlaps操作符有1个/2个可选参数 

$eventA : EventA( this overlaps[ 5s ] $eventB ) 
也就是: 
$eventA.startTimestamp < $eventB.startTimestamp < $eventA.endTimestamp < $eventB.endTimestamp && 
0 <= $eventA.endTimestamp - $eventB.startTimestamp <= 5s 

$eventA : EventA( this overlaps[ 5s, 10s ] $eventB ) 
也就是: 
$eventA.startTimestamp < $eventB.startTimestamp < $eventA.endTimestamp < $eventB.endTimestamp && 
5s <= $eventA.endTimestamp - $eventB.startTimestamp <= 10s 

6.overlappedby 

eventA : EventA( this overlappedby $eventB ) 
也就是: 
$eventB.startTimestamp < $eventA.startTimestamp < $eventB.endTimestamp < $eventA.endTimestamp 

overlappedby操作符有1个/2个可选参数 

$eventA : EventA( this overlappedby[ 5s ] $eventB ) 
也就是: 
$eventB.startTimestamp < $eventA.startTimestamp < $eventB.endTimestamp < $eventA.endTimestamp && 
0 <= $eventB.endTimestamp - $eventA.startTimestamp <= 5s 

$eventA : EventA( this overlappedby[ 5s, 10s ] $eventB ) 
也就是: 
$eventB.startTimestamp < $eventA.startTimestamp < $eventB.endTimestamp < $eventA.endTimestamp && 
5s <= $eventB.endTimestamp - $eventA.startTimestamp <= 10s 

7.starts 

$eventA : EventA( this starts $eventB ) 
也就是: 
$eventA.startTimestamp == $eventB.startTimestamp && 
$eventA.endTimestamp < $eventB.endTimestamp 

starts操作符有1个可选参数 

$eventA : EventA( this starts[ 5s ] $eventB ) 
也就是: 
abs( $eventA.startTimestamp - $eventB.startTimestamp ) <= 5s && 
$eventA.endTimestamp < $eventB.endTimestamp 

注意:时间间隔不能为负 

8.startedby 

$eventA : EventA( this startedby $eventB ) 
也就是: 
$eventA.startTimestamp == $eventB.startTimestamp && 
$eventA.endTimestamp > $eventB.endTimestamp 

starts操作符有1个可选参数 

$eventA : EventA( this starts[ 5s ] $eventB ) 
也就是: 
abs( $eventA.startTimestamp - $eventB.startTimestamp ) <= 5s && 
$eventA.endTimestamp > $eventB.endTimestamp 

注意:时间间隔不能为负 

9.during 
$eventA : EventA( this during $eventB ) 
也就是: 
$eventB.startTimestamp < $eventA.startTimestamp <= $eventA.endTimestamp < $eventB.endTimestamp 

during操作符有1个/2个/4个可选参数 

$eventA : EventA( this during[ 5s ] $eventB ) 
也就是: 
0 < $eventA.startTimestamp - $eventB.startTimestamp <= 5s && 
0 < $eventB.endTimestamp - $eventA.endTimestamp <= 5s 

$eventA : EventA( this during[ 5s, 10s ] $eventB ) 
也就是: 
5s <= $eventA.startTimestamp - $eventB.startTimestamp <= 10s && 
5s <= $eventB.endTimestamp - $eventA.endTimestamp <= 10s 

$eventA : EventA( this during[ 2s, 6s, 4s, 10s ] $eventB ) 
也就是: 
2s <= $eventA.startTimestamp - $eventB.startTimestamp <= 6s && 
4s <= $eventB.endTimestamp - $eventA.endTimestamp <= 10s 

10.includes 
$eventA : EventA( this includes $eventB ) 
也就是: 
$eventA.startTimestamp < $eventB.startTimestamp <= $eventB.endTimestamp < $eventA.endTimestamp 

includes操作符有1个/2个/4个可选参数 

$eventA : EventA( this includes[ 5s ] $eventB ) 
也就是: 
0 < $eventB.startTimestamp - $eventA.startTimestamp <= 5s && 
0 < $eventA.endTimestamp - $eventB.endTimestamp <= 5s 

$eventA : EventA( this includes[ 5s, 10s ] $eventB ) 
也就是: 
5s <= $eventB.startTimestamp - $eventA.startTimestamp <= 10s && 
5s <= $eventA.endTimestamp - $eventB.endTimestamp <= 10s 

$eventA : EventA( this includes[ 2s, 6s, 4s, 10s ] $eventB ) 
也就是: 
2s <= $eventB.startTimestamp - $eventA.startTimestamp <= 6s && 
4s <= $eventA.endTimestamp - $eventB.endTimestamp <= 10s 

11.finishes 
$eventA : EventA( this finishes $eventB ) 
也就是: 
$eventB.startTimestamp < $eventA.startTimestamp && 
$eventA.endTimestamp == $eventB.endTimestamp 

finishes操作符有1个可选参数 

$eventA : EventA( this finishes[ 5s ] $eventB ) 
也就是: 
$eventB.startTimestamp < $eventA.startTimestamp && 
abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s 

注意:时间间隔不能为负 

12.finishedby 
$eventA : EventA( this finishedby $eventB ) 
也就是: 
$eventA.startTimestamp < $eventB.startTimestamp && 
$eventA.endTimestamp == $eventB.endTimestamp 

finishedby操作符有1个可选参数 

$eventA : EventA( this finishedby[ 5s ] $eventB ) 
也就是: 

抱歉!评论已关闭.