来自小韩

什么是Esper

想要认识Esper,先要了解CEP(Complex Event Processing),到处都有,并且各方理解也有偏差,我就不赘述了。

Esper就是CEP的一个java的开源实现。

Esper官方网址:http://www.espertech.com/

Esper的特性

在探究Esper特性之前,我们先总结一下复杂事件的特性:

  • 类型多样,不易建模
  • 场景不可控,随时可能新增场景
  • 逻辑复杂,难于描述
  • 既需要汇总规律,又不准数据落地。

场景举例:

股市实时K线图、网站恶意操作监测、用户登入控制、实时数据统计等

针对复杂事件的这些特性,Esper具有相应的性质:

  • 实时响应
  • 极速扩展新事件
  • 语法描述能力强大、类sql

事件和处理流程

一个基本的例子

引用Esper就不说了,直接搜maven esper,添加以来就好。

/*定义事件模型*/
public class Coder {
private String Name;
private int age;
private double Salary;
//省略getter/setter
}
//
public class HelloEsperApp {
public static void main(String[] args) throws InterruptedException {
EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();
EPAdministrator admin = epService.getEPAdministrator(); //指定事件模型
String coderModel = Coder.class.getName(); //描述复杂事件
String epl = "select name,salary,age from " + coderModel;
EPStatement state = admin.createEPL(epl); //添加事后处理
state.addListener(new HelloEsperListener());
EPRuntime runtime = epService.getEPRuntime(); //模拟事件发生
for (int i = 0; i < 10; i++) {
Coder coder = new Coder();
coder.setName("coder"+i);
coder.setAge(20+i);
runtime.sendEvent(coder);
}
}
}
import com.espertech.esper.client.UpdateListener;
/** 实现UpdateListener接口,来定义事件的后置处理过程 **/
public class HelloEsperListener implements UpdateListener { public void update(EventBean[] arg0, EventBean[] arg1) {
try {
System.out.println("coder: name-"+arg0[0].get("name") + " age-"+arg0[0].get("age"));
}catch(Exception e) {
e.printStackTrace();
}
}

小心的分享:笔者认为任何一个项目的学习都可以分为两步,1.看他暴露了多少给你(用起来是否清晰);2.看他隐藏了多少细节(实现得是否精致)

一张图简单描述一下Esper给我们暴露了什么:



其中,后置处理方式的subscribe本文暂不提及。

Esper支持的模型类型

前面的例子中,我们使用一个bean作为事件模型。这样做很多时候都存在局限性,当有新的事件模型需要被加入时,我们必须要定义新的类,实际上,在实际应用中,bean很少被使用。

Esper支持丰富的事件模型定义方式,包括java类、Map、List、XML。

例如使用Map来定义事件模型:

        Map<String, Object> blog = new HashMap<String, Object>();
blog.put("url", String.class);
blog.put("title", String.class); Map<String, Object> coder = new HashMap<String, Object>();
coder.put("name", String.class);
coder.put("salary", int.class);
coder.put("friends", List.class);
coder.put("blogKey", "Blog"); // 注册blog模型到esper
admin.getConfiguration().addEventType("Blog", blog);
// 注册coder到Esper
admin.getConfiguration().addEventType("Coder", coder);

这之后,我们就可以对Coder事件模型进行EPL事件描述了。

EPL语法

关于语法,我们大致讲一下,到能帮助大家整体理解Esper的程度,之后会单独写文章来分享语法技巧。

基本语法

以上面的Coder模型为例,类SQL部分,我们快速带过:

#实时计算出当前进入引擎的所有程序员的平均工资、最高工资。
select name,Blog.title,salary,avg(salary) as avgSalary,max(salary) as maxSalary from Coder where salary>1000;
#其他的例如 and、or、not、in、order by、group by、having、join等基本都与SQL标准一致

与SQL不同的地方,主要体现了实时性,与sql的持久数据形成对比我们列四点最重要的学习一下:insert、窗格、context、pattern。

insert

首先用SQL的视角去想象,好像把数据保存起来这样的动作在Esper这样实时处理的工具中好像确实没有场景。

实际上insert在Esper中做的是转发的角色。即把某事件模型类的事件经过EPL运算后,insert成另外一种事件,去触发另外事件的处理流程。看例子:

//在前文Coder的基础上,给Coder加上团队标志,再定义一个Team事件模型
Map<String, Object> coder = new HashMap<String, Object>();
coder.put("name", String.class);
coder.put("salary", int.class);
coder.put("teamName", String.class); Map<String, Object> team = new HashMap<String, Object>();
team.put("teamName", String.class);
team.put("totalSalary", int.class);
admin.getConfiguration().addEventType("Coder", coder);
admin.getConfiguration().addEventType("Team", team); String epl4CoderIn = "insert Team(teamName, totalSalary) select teanName,sum(salary) as totalSalary from Coder groupby teamName";
String epl4TeamIn = "select teamName, totalSalary from Team"; EPStatement state = admin.createEPL(epl4CoderIn);
EPStatement state = admin.createEPL(epl4TeamIn);
state.addListener(new TeamEventListener());

这时,每当有Coder类型的事件流入,就转化为新的Team事件去触发Team的流程。Esper可以基于此实现事件流。

窗格

窗格应该是最有别于SQL的特性了,Esper的事件收集器支持事件积攒,分为两种积攒方式,时间和数量。

  • 时间窗格

    select name, avg(salary) from Coder.win:time(5 sec);

    计算5秒内进入引擎的Coder的平均工资,看图理解:



    每有新的事件进入,就会触发事件收集器回溯5秒,找到这五秒内收到的所有事件,并一同发给后置处理器。

  • 时间批量窗格

    select name, avg(salary) from Coder.win:time_batch(5 sec);

    看图理解:



    在事件批量窗格中,事件的进入不触发后置处理,只有满了一个批量单位才会进行提交。例如在股市K线图的实时绘制中就采用这种机制。

    事件窗格支持的时间定义,小到毫秒大到年,包括msec、sec、min、hour、day、week、month、year。例如我们要定义一个周期为一天5小时20分的窗格,可以写作:

    1 day 5 hour 20 min

  • 数量窗格

数量窗格跟事件窗格一样也分普通和批量,我们先来看一下语法例子:

select name, avg(salary) from Coder.win:length(5);
select name, avg(salary) from Coder.win:length_batch(5);

非批量情况下,事件进入就会触发收集引擎回溯最近的五个事件,批量提交给后置处理器;批量情况下则是,每满5个事件才提交一次,不满则等待。

context

即使是同样的事件,也有很多情况下需要分组处理,context为Esper提供一种组别定义的能力,从而让事件流入不同的处理组中我们结合前面的窗格举一个实际的例子。

场景:游戏对局匹配

规则:十个人一组,进行5V5游戏,玩家按等级分为青铜、白银、黄金、白金、钻石、王者六种,为了保证游戏竞技性,只有级别相同的玩家才能共同进行一局游戏。

如果只是十个人对战,那个很简单,我们只需要按照前文介绍的,数量批量提交窗口,定义一个容量为10的窗格,每满十个,就交给后置处理器去创建对局。但是现在的场景又加入了玩家水平等级制,这时,就需要Context帮忙了。

        // 省略Player模型的创建过程
// 创建context以Player的level属性作为组分割条件
String createContext = "create context forLevel partition by level from Player";
// 带上context前缀
String match = "context forLevel select * from Player.win:length_batch(10)"; admin.createEPL(createContext);
EPStatement state = admin.createEPL(match);
state.addListener(new StartGameListener());

pattern

pattern具有极强大的逻辑描述能力,本文暂不介绍,后续独立发文。

进程模型分析

其实看过了前面的内容这一部分,我们先搬官网的图出来看看:





不知道大家什么感觉,总之我是不愿意看的...我们来翻译一下第一张图:



官网给出的第二张事件流收集原理实际上可以看做是引擎入口处的EPL语句的解析过程。引擎中将事件分了三级缓存:

入门先到这里!

Esper复杂事务处理一小时入门的更多相关文章

  1. 《Qt Quick 4小时入门》学习笔记4

    http://edu.csdn.net/course/detail/1042/14806?auto_start=1 Qt Quick 4小时入门 第七章:处理鼠标与键盘事件 1.处理鼠标事件 鼠标信号 ...

  2. 《Qt Quick 4小时入门》学习笔记3

    http://edu.csdn.net/course/detail/1042/14807?auto_start=1 Qt Quick 4小时入门 第八章:Qt Quick中的锚(anchors)布局 ...

  3. 《Qt Quick 4小时入门》学习笔记2

    http://edu.csdn.net/course/detail/1042/14805?auto_start=1   Qt Quick 4小时入门 第五章:Qt Quick基本界面元素介绍   1. ...

  4. 《Qt Quick 4小时入门》学习笔记

    http://edu.csdn.net/course/detail/1042/14804?auto_start=1   Qt Quick 4小时入门 第五章:Qt Quick里的信号与槽   QML中 ...

  5. 一小时入门PHP

    [版权申明:本文系作者原创,转载请注明出处] 文章出处:[http://blog.csdn.net/sdksdk0/article/details/52332296](http://blog.csdn ...

  6. 一小时入门 Python

    因为需求, 需要用到py, 所以来学学py, 因为有java基础 一小时入门py语法是不成问题的, 但是仅仅入门基础语法而已, 不涉及算法,不涉及大数据,机器学习,人工智能, 但是py这么火爆,就在于 ...

  7. iOS 开发-- Runtime 1小时入门教程

    1小时让你知道什么是Objective-C Runtime,并对它有一定的基本了解,可以在开发过程中运用自如. 三.Objective-C Runtime到底是什么东西? 简而言之,Objective ...

  8. mongodb 两小时入门

    传统的计算机应用大多使用关系型数据库来存储数据,比如大家可能熟悉的MySql, Sqlite等等,它的特点是数据以表格(table)的形式储存起来的.数据库由一张张排列整齐的表格构成,就好像一个Exc ...

  9. 2小时入门Robot Framework

    1.介绍 1.1.介绍Robot Robot Framework是一个基于关键字驱动的自动化测试框架.通过该框架,测试人员可使用python封装关键字,并在非代码环境下使用关键字构建可被执行的测试用例 ...

随机推荐

  1. 自平衡二叉(查找树/搜索树/排序树) binary search tree

    在计算机科学中,AVL树是最先发明的自平衡二叉查找树.AVL树得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在 1962 年的论文 "An alg ...

  2. loj2542 「PKUWC2018」随机游走 【树形dp + 状压dp + 数学】

    题目链接 loj2542 题解 设\(f[i][S]\)表示从\(i\)节点出发,走完\(S\)集合中的点的期望步数 记\(de[i]\)为\(i\)的度数,\(E\)为边集,我们很容易写出状态转移方 ...

  3. Reactor模式,或者叫反应器模式 - 为什么用多路io复用提供吞吐量

    Reactor这个词译成汉语还真没有什么合适的,很多地方叫反应器模式,但更多好像就直接叫reactor模式了,其实我觉着叫应答者模式更好理解一些.通过了解,这个模式更像一个侍卫,一直在等待你的召唤,或 ...

  4. Android Studio & eclipse 调试技巧

    如上图设置多个断点,开启调试.想跨断点移动到下一个断点,点击如下图1箭头,程序将运行一个断点到下一个断点之间需要执行的代码.如果后面代码没有断点,再次点击该按钮将会执行完程序.点击箭头2指向的按钮,可 ...

  5. 解题:JSOI 2008 Blue Mary的战略地图

    题面 这大概不算是从零开始的DP学习系列,这不是最大子矩形吗=.= 定义$dp[x][y][xx][yy]$表示第一张地图中右下角为$(x,y)$,第二张地图中右下角为$(xx,yy)$的最大公共子矩 ...

  6. python 资产扫描01

    本地建立的三个文件: Asset1.txt 用来保存扫描到的资产 Asset2.txt 用来导入给定的资产 Repeat.txt 保存重复的资产 程序的功能: 1.资产扫描,以 位置:资产 格式保存到 ...

  7. NLP分词

    英文分词: #英文分词 import nltk sentence="hello,world" tokens=nltk.word_tokenize(sentence) print(t ...

  8. gulp+webpack配置

    转自:https://www.jianshu.com/p/2549c793bb27 gulp gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优化,而且在开 ...

  9. 关于dubbo的架构

    dubbo是国内一个十分受欢迎的分布式rpc框架. 这篇博客是从dubbo官网出发,来说明下dubbo的技术架构.首先我们看下官网的架构图. 节点角色说明: Provider: 暴露服务的服务提供方. ...

  10. 数据分析与展示---Pandas库入门

    简介 一:Pandas库的介绍 二:Pandas库的Series类型 (一)索引 (1)自动索引 (2)自定义索引 (二)Series类型创建 (1)列表创建 (2)标量值创建 (3)字典类型创建(将 ...