escper的使用整理

来源:互联网 发布:人工智能的弊端英文 编辑:程序博客网 时间:2024/05/16 12:01

 一、CEP和ESP的概念

CEP:复杂事件处理,是一种新兴的基于事件流的技术,它用于处理事件、从事件流中发现复杂模式。它将系统数据看做不同类型的事件,通过分析事件间的关系,建立不同事件关系序列库,利用过滤、关联、聚合等技术,最终由简单事件产生高级事件或商业流程。

ESP:事件流处理,目的是从事件流中获得有用的事件,进而从中获得有用信息。

CEP/ESP适合的场景包括:监控、犯罪预防、网络攻击、市场趋势分析。

比如示例:

import com.espertech.esper.client.EPAdministrator;import com.espertech.esper.client.EPRuntime;import com.espertech.esper.client.EPServiceProvider;import com.espertech.esper.client.EPServiceProviderManager;import com.espertech.esper.client.EPStatement;import com.espertech.esper.client.EventBean;import com.espertech.esper.client.UpdateListener;/**
1. 这是一个EventClass对象 */public class Apple {    private int id;    private int price;    public int getId()    {        return id;    }    public void setId(int id)    {        this.id = id;    }    public int getPrice()    {        return price;    }    public void setPrice(int price)    {        this.price = price;    }}// 2. 创建一个class实现UpdateListener接口class AppleListener implements UpdateListener{    public void update(EventBean[] newEvents, EventBean[] oldEvents)    {        if (newEvents != null)        {            Double avg = (Double) newEvents[0].get("avg(price)");            System.out.println("Apple's average price is " + avg);        }    }}


调用:

import com.espertech.esper.client.EPAdministrator;import com.espertech.esper.client.EPRuntime;import com.espertech.esper.client.EPServiceProvider;import com.espertech.esper.client.EPServiceProviderManager;import com.espertech.esper.client.EPStatement;import com.espertech.esper.client.EventBean;import com.espertech.esper.client.UpdateListener;/** */public class Test {    public static void main(String[] args) {
// 创建一条语句(类似于JDBC里面的Statement的)        EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();        EPAdministrator admin = epService.getEPAdministrator();        String product = Apple.class.getName();
// 获取类SQL语句.         String epl = "select avg(price) from " + product + ".win:length_batch(3)";        EPStatement state = admin.createEPL(epl);   
// 添加一个监听器        state.addListener(new AppleListener());
// 发送事件        EPRuntime runtime = epService.getEPRuntime();        Apple apple1 = new Apple();        apple1.setId(1);        apple1.setPrice(5);        runtime.sendEvent(apple1);// 发送事件        Apple apple2 = new Apple();        apple2.setId(2);        apple2.setPrice(2);        runtime.sendEvent(apple2);      // 发送事件        Apple apple3 = new Apple();        apple3.setId(3);        apple3.setPrice(5);        runtime.sendEvent(apple3);    // 发送事件    }}

输出:4.0

使用Esper的基本步骤:

  1. 创建一个EventClass
  2. 创建一个class实现UpdateListener接口
  3. 创建一个Configuration实例
  4. 通过EPServiceProviderManager获得EPServiceProvider对象
  5. 通过EPServiceProder和EPL查询语句,创建EPStatement对象
  6. 将listener和EPStatement挂钩
  7. 使用epService.getEPRuntime().sendEvent(event)向引擎发送事件
我们要做的事情就是定义DSL语言,然后让它执行。

关于如何让EPS调用自定义函数?

二、关于EPL能够处理的事件类型
目前EPL能够处理的事件类型:POJO、MAP、ObjectArray、XML
2.1 POJO
Esper要求对每一个私有属性要有getter方法。不必按JavaBean规定的格式,但getter方法是必须的。也支持复杂的数据结构
比如如下的一个POJO对象
import java.util.List;import java.util.Map;public class Person{String name;int age;List<Child> children;Map<String, Integer> phones;Address address;public String getName(){return name;}public int getAge(){return age;}public List<Child> getChildren(){return children;}public Map<String, Integer> getPhones(){return phones;}public Address getAddress(){return address;}}class Child{String name;int gender;// 省略getter方法}class Address{String road;String street;int houseNo;// 省略getter方法}
支持这样写类SQL语句:
#select age,children,address from Person where name=''张三'
这样得到的children是一个列表,如果不想要所有的,而是想要第二个,那Person需要改一下
import java.util.List;import java.util.Map;public class Person{String name;int age;List<Child> children;Map<String, Integer> phones;Address address;public String getName(){return name;}public int getAge(){return age;}        // 可以这样写get的方法public Child getChildren(int index){return children.get(index);}public int getPhones(String name){return phones.get(name);}public Address getAddress(){return address;}// Address,Child不变}
对应的EPL如下:
#select children[1],phones('home'),address.road from Person where name='张三'
select 后面的这些列其实就是从POJo中的get方法拿数据的。

Esper支持事件更新,对此Esper需要提供setter方法。示例如下:

import java.util.List;import java.util.Map;public class Person{String name;int age;List<Child> children;Map<String, Integer> phones;Address address;public String getName(){return name;}public int getAge(){return age;}public Child getChildren(int index){return children.get(index);}// 此方法用于phones属性的更新  、 支持set方法public void setPhones(String name, Integer number){phones.put(name, number);}public int getPhones(String name){return phones.get(name);}public Address getAddress(){return address;}// Address,Child不变}
对应的EPL如下:
#update Person set  phones('home') = 123456789 where name='张三'

2. Map
Esper支持原生Java map结构的事件。相对POJO,Map结构更利于热加载。不需要重启JVM,如果系统对重启比较敏感,建议使用Map来定义事件结构。

import java.util.HashMap;import java.util.List;import java.util.Map;import com.espertech.esper.client.EPAdministrator;import com.espertech.esper.client.EPServiceProvider;import com.espertech.esper.client.EPServiceProviderManager;public class PersonMap{public static void main(String[] args){EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();EPAdministrator admin = epService.getEPAdministrator();// Person定义Map<String,Object> person = new HashMap<String,Object>();person.put("name", String.class);person.put("age", int.class);person.put("children", List.class);person.put("phones", Map.class);// 注册Person到Esperadmin.getConfiguration().addEventType("Person", person);}}
对应的EPL跟POJO没有区别:
#select age,children from Person where name='张三'
3. Object Array
对象数组和Map很像,基本没有差别。只是定义方式不一样。

三、关于进程模型
Esper是怎么处理事件的,即Esper的进程模型。
3.1 UpdaterListener是Esper提供的一个接口,用于监听某个EPL在引擎中的运行情况,即事件进入并产生结果后会通知UpdateListener. 接口如下:
package com.espertech.esper.client;import com.espertech.esper.client.EventBean;public interface UpdateListener{    public void update(EventBean[] newEvents, EventBean[] oldEvents);}
接口就很简单,就一个update方法,包括两个EventBean数组。
#EPL: select name from User
#newEvents[0].get("name")   能得到进入的User事件的name属性值

2. Insert and remove stream
Insert表示进入引擎,remove表示移出引擎。

3. Filter and where-clause
EPL有两种过滤事件的方式:一种是过滤事件进入view,即Filter, 另一种是让事件都进入view,但不触发UpdateListener,即where 子句。
// Apple事件进入Esper,只有amount > 200才进入win.length,并且length长度为5
EPL: select * from Apple(amount > 200).win:length(5)

4. 聚合与分组
类SQL里面的sum与group by 操作类似的。
// 统计进入的5个Apple事件,amount的总数是多少
select sum(amount) from Apple.win:length_batch(5)

四、关于context
4.1 context基本语法
create context context_name partition [by] event_property [and event_property [and ...]] from stream_def [, event_property [...] from stream_def] [, ...]
说明:
context_name: 为context的名字,并且唯一。如果重复,会说明已存在
event_property为事件的属性名,多个属性名之间用and连接,也可以用逗号连接。



参考文档:
http://blog.csdn.net/luonanqin/article/details/10946329












原创粉丝点击