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
| 1 | // 引用数据类型类定义 |
| 2 | public class orderBean { |
| 3 | private String key; |
| 4 | private String value; |
| 5 | public String getKey() { |
| 6 | return key; |
| 7 | } |
| 8 | public void setKey(String key) { |
| 9 | this.key = key; |
| 10 | } |
| 11 | public String getValue() { |
| 12 | return value; |
| 13 | } |
| 14 | public void setValue(String value) { |
| 15 | this.value = value; |
| 16 | } |
| 17 | } |
orderEvent.java
| 1 | // 事件流单元实现类 |
| 2 | public class orderEvent { |
| 3 | //基本数据类型 |
| 4 | private String name; |
| 5 | private int salary; |
| 6 | // 集合数据类型,数据项成员为引用数据类型 |
| 7 | private List<orderBean> orderBeans; |
| 8 | // 集合数据类型,KEY为基本数据类型,VALUE为引用数据类型 |
| 9 | private Map<Integer, orderBean> orderMap; |
| 10 | // 引用数据类型 |
| 11 | private orderBean bean; |
| 12 | // 对应事件流中orderBeans属性获取 |
| 13 | public String getOrderBeans(int index) { |
| 14 | return orderBeans.get(index).getValue(); |
| 15 | } |
| 16 | // 对应事件流中orderBeans属性设置 |
| 17 | public void setOrderBeans(List<orderBean> orderBeans) { |
| 18 | this.orderBeans = orderBeans; |
| 19 | } |
| 20 | // 测试使用 |
| 21 | public String getOrderBeanListString(int index){ |
| 22 | orderBean bean = orderBeans.get(index); |
| 23 | return bean.getKey()+":"+bean.getValue(); |
| 24 | } |
| 25 | // 对应事件流中orderMap属性获取 |
| 26 | public String getOrderMap(int id) { |
| 27 | return orderMap.get(id).getValue(); |
| 28 | } |
| 29 | // 对应事件流中orderMap属性设置 |
| 30 | public void setOrderMap(Map<Integer, orderBean> orderMap) { |
| 31 | this.orderMap = orderMap; |
| 32 | } |
| 33 | public orderBean getBean() { |
| 34 | return bean; |
| 35 | } |
| 36 | public void setBean(orderBean bean) { |
| 37 | this.bean = bean; |
| 38 | } |
| 39 | public orderEvent() { |
| 40 | } |
| 41 | public orderEvent(String name, int salary) { |
| 42 | this.name = name; |
| 43 | this.salary = salary; |
| 44 | } |
| 45 | public String getName() { |
| 46 | return name; |
| 47 | } |
| 48 | public void setName(String name) { |
| 49 | this.name = name; |
| 50 | } |
| 51 | public int getSalary() { |
| 52 | return salary; |
| 53 | } |
| 54 | public void setSalary(int salary) { |
| 55 | this.salary = salary; |
| 56 | } |
| 57 | } |
orderListener.java
| 1 | /** |
| 2 | * 用于监听某个EPL在引擎中的运行情况,事件进入并产生结果后会回调UpdateListener |
| 3 | * 必须实现 UpdateListener 接口 |
| 4 | */ |
| 5 | public class orderListener implements UpdateListener { |
| 6 | |
| 7 | /** |
| 8 | * arg0对应newEvent,arg1对应oldEvent |
| 9 | */ |
| 10 | @Override |
| 11 | public void update(EventBean[] arg0, EventBean[] arg1) { |
| 12 | if (null != arg0) { |
| 13 | System.out.println("orderEvent Count is "+arg0[0].get("result")); |
| 14 | } else { |
| 15 | System.out.println("EventBean is Null "); |
| 16 | } |
| 17 | } |
| 18 | } |
| 19 | |
| 20 | |
| 21 | orderMainTest.java |
| 22 | |
| 23 | public class orderMainTest { |
| 24 | public static void main(String[] args){ |
| 25 | // 添加配置(包所在路劲),方面后面的引用自动添加包名前缀 |
| 26 | Configuration config = new Configuration(); |
| 27 | config.addEventTypeAutoName("cn.chenx.esper"); |
| 28 | // |
| 29 | EPServiceProvider epServiceProvider = EPServiceProviderManager.getDefaultProvider(config); |
| 30 | EPAdministrator epAdmin = epServiceProvider.getEPAdministrator(); |
| 31 | // 计算平均数值 |
| 32 | String epsql = "select avg(salary) as result from orderEvent.win:length_batch(3)"; |
| 33 | epAdmin.createEPL(ctsql); |
| 34 | EPStatement epstate = epAdmin.createEPL(epsql); |
| 35 | epstate.addListener(new orderListener()); |
| 36 | EPRuntime epRuntime = epServiceProvider.getEPRuntime(); |
| 37 | // |
| 38 | for (int i=0;i<3;i++){ |
| 39 | int seed = (int)(Math.random()*100); |
| 40 | orderEvent event = new orderEvent("张"+seed, 100+seed); |
| 41 | System.out.println("seed name:"+event.getName()+",salary:"+event.getSalary()); |
| 42 | orderBean bean = new orderBean(); |
| 43 | bean.setKey("BeanKey:"+i); |
| 44 | bean.setValue("BeanValue:"+i); |
| 45 | event.setBean(bean); |
| 46 | List<orderBean> list = new ArrayList<orderBean>(); |
| 47 | for (int j=0;j<10;j++){ |
| 48 | bean = new orderBean(); |
| 49 | bean.setKey("ListKey:"+j); |
| 50 | bean.setValue("ListValue:"+j); |
| 51 | list.add(bean); |
| 52 | } |
| 53 | event.setOrderBeans(list); |
| 54 | Map<Integer, orderBean> map = new HashMap<Integer, orderBean>(); |
| 55 | for (int k=0; k<10;k++){ |
| 56 | bean = new orderBean(); |
| 57 | bean.setKey("MapKey"+k); |
| 58 | bean.setValue("MapValue"+k); |
| 59 | map.put(k, bean); |
| 60 | } |
| 61 | event.setOrderMap(map); |
| 62 | epRuntime.sendEvent(event); |
| 63 | } |
| 64 | } |
| 65 | } |
输出结果:
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

浙公网安备 33010602011771号