Esper教程 —— Esper 进程模型是什么(3)

进程模型

主要解释一下 Esper 是怎么处理事件的,即Esper的进程模型。

1、UpdateListener

UpdaterListener 是 Esper 提供的一个接口,用于监听某个 EPL 在引擎中的运行情况,即事件进入并产生结果后会通知 UpdateListener。接口如下

import com.espertech.esper.client.EventBean;

public interface UpdateListener {
    public void update(EventBean[] newEvents, EventBean[] oldEvents);
}

接口很简单,就一个 update 方法,其中包括两个 EventBean 数组。EventBean 中有一个最常用的 get 方法,是用来得到 EPL 中某个字段的值。

如下代码:假设 newEvents 长度为1

// 能得到进入的User事件的name属性值
EPL:select name from User
newEvents[0].get("name")

// 能得到5秒内进入引擎的User事件数量有多少
EPL:select count(*) from User.win:time(5 sec)
newEvents[0].get("count(*)");

get 方法最常用,此外还有 getUnderlying 等方法,

2、Insert 和 Remove Stream

Insert 表示进入引擎,Remove 表示移出引擎,事件在 Esper 中会因为某类EPL才会经历这两种状态。对应于 UpdateListener 接口就是 newEvents 和 oldEvents,因为处于这两种状态的事件不一定只有一个,所以 newEvents 和 oldEvents 就是数组形式。

举例如下

EPL:select * from User

UpdateListener.png

从此图可以看出,随着时间推移,每个进入到引擎的 W 事件都是 newEvents,即 Insert StreamW 后括号里的值为属性值(500、100、...),可忽略。

有人可能要问了,为什么这里 oldeEvents 什么都没有。那是因为 EPL 的关系。看下面的例子。

EPL:select * from User.win:length(5)

UpdateListener-2.png

注:win:length(5) 是个 view(可以把view理解为一个窗口),这里先暂时理解为 Esper 开放一个空间并最多可同时存放 5 个事件(此空间其实就是大小为 5 的数组)

由图可知,length window 可存放 w1,w2 等事件,在 w6 事件进入之前,每个事件进入都属于 newEvents

直到 w6 进入后,length window 不能容纳 w1~w6 的事件,必须把 w1 事件移出,即 w1 为 oldEvents

length window 就像一个队列,每当事件进入队列时,就会触发 updateListener 并告知有新事件进入。当队列满了,再进入一个新事件时,Esper 会触发 UpdateListener 告知有新事件进入并且有旧事件移出,正如上图所示的 w6 和 w1

实际上这个EPL触发监听器都只能看到 newEvents,看不到 oldEvents。如果想看到 oldEvents,EPL 要改写一下:

EPL:select irstream * from User.win:length(5)

默认情况下,Esper 认为你只想让 newEvents 触发监听器,即 istream(insert stream)。如果想让 oldEvents 触发监听器,那么为 rstream(remove stream)。如果两个都想,那么为 irstream。当然这个默认情况是可以配置的,以后会说到这个问题。

3、Filter 过滤、Where 条件查询

EPL 有两种过滤事件的方式,

  • 一种是过滤事件进入view,即 Filter

  • 一种是让事件都进入view,但不触发 UpdateListener,即 where 子句。

Filter:过滤器
-- Apple事件进入Esper,只有 amount 大于 200 才能进入 win:length,并且 length 长度为5  
EPL:select * from Apple(amount>200).win:length(5)

UpdateListener-3.png

从图上可以看出,只有amount大于200,Esper才允许Apple事件进入view,并且作为一个 newEvent 触发 UpdateListener

Where:条件查询
-- Apple事件进入Esper 并进入win:length(5),但是只有 amount 大于 200 的才能触发 
UpdateListener  EPL:select * from Apple.win:length(5) where amount>200

UpdateListener-4.png

由图上可以看出,Apple事件先进入view,然后才被 where 子句过滤,以至于被过滤掉的事件不会作为 newEvent 触发 UpdateListener

4、Aggregation 聚合、 Grouping 分组

之前说过 EPL 是类 SQL 语法,所以也会有聚合和分组的功能。语法和SQL基本一样,如下代码:

-- 统计进入的5个Apple事件,amount的总数是多少  
select sum(amount) from Apple.win:length_batch(5)  

-- 统计进入的5个Apple事件,amount的总数是多少,并按照price分组  
select price, sum(amount) from Apple.win:length_batch(5) group by price  
  
-- 统计进入的5个Apple事件,amount的总数和name,并按照price分组  
select price, name, sum(amount) from Apple.win:length_batch(5) group by price

最后一个和前一个的区别在于 name 也在统计的范围内,所以当 name 和 price 都一样的两个事件进入Esper,会有两个一模一样的事件作为 newEvent 触发 UpdaterListener,即 price,name,sum(amount) 都一样。当然要是 group by name, price 的话,就只会有一个事件触发监听器了。


未经允许请勿转载:程序喵 » Esper教程 —— Esper 进程模型是什么(3)

点  赞 (0) 打  赏
分享到: