Esper系列(一)初探

Esper介绍

Esper是一个Java开发并且开源的轻量级和可扩展的事件流处理和复合事件处理引擎,并提供了定制的事件处理语言(EPL)。

应用场景

某个用户在请求登录服务时,n秒内连续m次未登录成功,可视为该ip在暴力破解密码。又或者:用户在页面上的操作间隔超过n秒即认为该用户已关闭该网页。也许上面的几个例子不够好或者已经有别的方式实现,但是Esper确实能够将其抽象成多个关联的事件进行处理。

源码地址: http://www.espertech.com/esper/distributions/

 

事件的分类

简单事件处理(SEP):基于单个事件,即:触发并响应,通常采用点对点(Queue)和发布和订阅(Topic)[类似观察者模式];
事件流处理(ESP):事件的出发需要分析事件流,分析采用基于事件窗口和事件数量窗口的方式;
复合事件处理(CEP):先捕获各种细微基础事件,然后分析整体找出的更有意义的事件。

 

EPL与SQL的区别

SQL:每执行一次SQL语句就会执行一次查询,存储的是具体的数据。
EPL:当满足到设定的执行条件后才触发执行,存储的是具体的功能性操作(如:查询、删除、插入等)而非操作所需的数据。

  

Esper的适配器

输入输出适配器,API提供对实时数据流输入到Esper容器,或事件输出的各种途径或方式,该过程需将实时数据流转成实时事件流,并以Object、Map、Node形式的事件发送的引擎;

输入适配种类:
CVS,Spring JMS,HTTP,Socket、关系型数据库

输出适配种类:
Spring JMS,HTTP,XML,JSON

 

事件类型

POJO、Map、Object Array,XML

 

示例程序:

orderBean.java

// 引用数据类型类定义
public class orderBean {
    private String key;
    private String value;
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
}

orderEvent.java

// 事件流单元实现类
public class orderEvent {
    //基本数据类型
    private String name;
    private int salary;
    // 集合数据类型,数据项成员为引用数据类型
    private List<orderBean> orderBeans;
    // 集合数据类型,KEY为基本数据类型,VALUE为引用数据类型
    private Map<Integer, orderBean> orderMap;
    // 引用数据类型
    private orderBean bean;
    // 对应事件流中orderBeans属性获取
    public String getOrderBeans(int index) {
        return orderBeans.get(index).getValue();
    }
    // 对应事件流中orderBeans属性设置
    public void setOrderBeans(List<orderBean> orderBeans) {
        this.orderBeans = orderBeans;
    }
    // 测试使用
    public String getOrderBeanListString(int index){
        orderBean bean = orderBeans.get(index);
        return bean.getKey()+":"+bean.getValue();
    }
    // 对应事件流中orderMap属性获取
    public String getOrderMap(int id) {
        return orderMap.get(id).getValue();
    }
    // 对应事件流中orderMap属性设置
    public void setOrderMap(Map<Integer, orderBean> orderMap) {
        this.orderMap = orderMap;
    }
    public orderBean getBean() {
        return bean;
    }
    public void setBean(orderBean bean) {
        this.bean = bean;
    }
    public orderEvent() {
    }
    public orderEvent(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
}

orderListener.java

/**
* 用于监听某个EPL在引擎中的运行情况,事件进入并产生结果后会回调UpdateListener
* 必须实现 UpdateListener 接口
*/
public class orderListener implements UpdateListener {

    /**
     * arg0对应newEvent,arg1对应oldEvent
     */
    @Override
    public void update(EventBean[] arg0, EventBean[] arg1) {
        if (null != arg0) {
            System.out.println("orderEvent Count is "+arg0[0].get("result"));
        } else {
            System.out.println("EventBean is Null ");
        }
    }
}

orderMainTest.java

public class orderMainTest {
    public static void main(String[] args){
        // 添加配置(包所在路劲),方面后面的引用自动添加包名前缀
        Configuration config = new Configuration();
        config.addEventTypeAutoName("cn.chenx.esper");
        //
        EPServiceProvider epServiceProvider = EPServiceProviderManager.getDefaultProvider(config);
        EPAdministrator epAdmin = epServiceProvider.getEPAdministrator();
        // 计算平均数值
        String epsql = "select avg(salary) as result from orderEvent.win:length_batch(3)";
        epAdmin.createEPL(ctsql);
        EPStatement epstate = epAdmin.createEPL(epsql);
        epstate.addListener(new orderListener());
        EPRuntime epRuntime = epServiceProvider.getEPRuntime();
        //
        for (int i=0;i<3;i++){
            int seed = (int)(Math.random()*100);
            orderEvent event = new orderEvent("张"+seed, 100+seed);
            System.out.println("seed name:"+event.getName()+",salary:"+event.getSalary());
            orderBean bean = new orderBean();
            bean.setKey("BeanKey:"+i);
            bean.setValue("BeanValue:"+i);
            event.setBean(bean);
            List<orderBean> list = new ArrayList<orderBean>();
            for (int j=0;j<10;j++){
                bean = new orderBean();
                bean.setKey("ListKey:"+j);
                bean.setValue("ListValue:"+j);
                list.add(bean);
            }
            event.setOrderBeans(list);
            Map<Integer, orderBean> map = new HashMap<Integer, orderBean>();
            for (int k=0; k<10;k++){
                bean = new orderBean();
                bean.setKey("MapKey"+k);
                bean.setValue("MapValue"+k);
                map.put(k, bean);
            }
            event.setOrderMap(map);
            epRuntime.sendEvent(event);
        }
    }
}

输出结果:

log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
className is orderEvent
epsql:select avg(salary) as result from orderEvent.win:length_batch(3)
seed name:张50,salary:150
seed name:张59,salary:159
seed name:张86,salary:186
orderEvent Count is 165.0

 

你可能感兴趣的:(SP)