这篇文章使用了一个通俗的具体的例子来讲解Esper。在文末有两个版本的代码链接。通过这篇文章,你将会了解如何使用Esper,了解如何集成Esper到Spring框架中,了解如何使用Apache Active MQ和JMS来为Esper提供事件数据。
以下是一个非常简单的事件流处理示例(使用ESPER引擎)。在GitHub上可以看到一个完整的代码, ~ 链接在文末 ~。
复杂事件处理(CEP)或事件流流处理(ESP)是事件驱动系统中常用的技术。这些类型的系统实时响应事件数据流。通常情况下,常常应用于金融交易,欺诈识别和流程监控 - -需要识别、理解并快速响应数据事件流中的模式。
CEP系统就像典型数据库模型颠倒过来一样。一个典型的数据库存储数据
,并对数据
运行查询,而CEP存储`查询语句,对实时流进来的数据进行匹配查询或者说过滤和匹配。
要做到这一点基本上需要:
现在,这只是一个例子 - 假设你最关心的是核电站的临界温度等的信息。
假设我们的发电站有一个发电站,而且如果太热的话 - 非常糟糕的事情会发生。所以检测核电站核心地温度并在异常情况下发出警告信息是很重要地。
这里写图片描述
假设我们有温度计,每秒钟读取核心温度 - 并将数据发送到中央监控系统。
当发现3种类型的事件时,我们需要警告:
监控
只需告诉我们每10秒钟的平均温度 - 供参考
警告
警告我们,如果我们有2个连续的温度超过一定的阈值
危急
提醒我们,如果我们有4个连续事件,第一个事件超过一定的阈值,并且每个后续事件都大于最后一个 - 最后一个比第一个大1.5倍。这意味着有一个突然的不断升高的温度峰值 - 有点像下图。让我们假设这是一件非常糟糕的事情。
我们可以通过多种方式构建系统来处理这些需求。这篇文章将使用Esper来解决这个问题。
Esper大体这样处理:
当有匹配的数据的时候,Esper服务会向相关的listener发送消息。
select avg(value) as avg_val
from TemperatureEvent.win:time_batch(10 sec)
select * from TemperatureEvent "
match_recognize (
measures A as temp1, B as temp2
pattern (A B)
define
A as A.temperature > 400,
B as B.temperature > 400)
select * from TemperatureEvent
match_recognize (
measures A as temp1, B as temp2, C as temp3, D as temp4
pattern (A B C D)
define
A as A.temperature < 100,
B as (A.temperature < B.value),
C as (B.temperature < C.value),
D as (C.temperature < D.value) and D.value > (A.value * 1.5))
package com.cor.cep.event;
import java.util.Date;
/**
* Immutable Temperature Event class.
* The process control system creates these events.
* The TemperatureEventHandler picks these up
* and processes them.
*/
public class TemperatureEvent {
/** Temperature in Celcius. */
private int temperature;
/** Time temerature reading was taken. */
private Date timeOfReading;
/**
* Single value constructor.
* @param value Temperature in Celsius.
*/
/**
* Temerature constructor.
* @param temperature Temperature in Celsius
* @param timeOfReading Time of Reading
*/
public TemperatureEvent(int temperature,
Date timeOfReading) {
this.temperature = temperature;
this.timeOfReading = timeOfReading;
}
/**
* Get the Temperature.
* @return Temperature in Celsius
*/
public int getTemperature() {
return temperature;
}
/**
* Get time Temperature reading was taken.
* @return Time of Reading
*/
public Date getTimeOfReading() {
return timeOfReading;
}
@Override
public String toString() {
return "TemperatureEvent [" + temperature + "C]";
}
}
/**
* Auto initialise our service after Spring bean wiring is complete.
*/
@Override
public void afterPropertiesSet() throws Exception {
initService();
}
/**
* Configure Esper Statement(s).
*/
public void initService() {
Configuration config = new Configuration();
// Recognise domain objects in this package in Esper.
config.addEventTypeAutoName("com.cor.cep.event");
epService = EPServiceProviderManager.getDefaultProvider(config);
createCriticalTemperatureCheckExpression();
createWarningTemperatureCheckExpression();
createTemperatureMonitorExpression();
}
/**
* EPL to check for a sudden critical rise across 4 events,
* where the last event is 1.5x greater than the first.
* This is checking for a sudden, sustained escalating
* rise in the temperature
*/
private void createCriticalTemperatureCheckExpression() {
LOG.debug("create Critical Temperature Check Expression");
EPAdministrator epAdmin = epService.getEPAdministrator();
criticalEventStatement =
epAdmin.createEPL(criticalEventSubscriber.getStatement());
criticalEventStatement.setSubscriber(criticalEventSubscriber);
}
关键事件监听器
的例子。package com.cor.cep.subscriber;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.cor.cep.event.TemperatureEvent;
/**
* Wraps Esper Statement and Listener. No dependency on Esper libraries.
*/
@Component
public class CriticalEventSubscriber implements StatementSubscriber {
/** Logger */
private static Logger LOG =
LoggerFactory.getLogger(CriticalEventSubscriber.class);
/** Minimum starting threshold for a critical event. */
private static final String CRITICAL_EVENT_THRESHOLD = "100";
/**
* If the last event in a critical sequence is this much greater
* than the first - issue a critical alert.
*/
private static final String CRITICAL_EVENT_MULTIPLIER = "1.5";
/**
* {@inheritDoc}
*/
public String getStatement() {
// Example using 'Match Recognise' syntax.
String criticalEventExpression = "select * from TemperatureEvent "
+ "match_recognize ( "
+ "measures A as temp1, B as temp2, C as temp3, D as temp4 "
+ "pattern (A B C D) "
+ "define "
+ " A as A.temperature > " + CRITICAL_EVENT_THRESHOLD + ", "
+ " B as (A.temperature < B.temperature), "
+ " C as (B.temperature < C.temperature), "
+ " D as (C.temperature < D.temperature) "
+ "and D.temperature > "
+ "(A.temperature * " + CRITICAL_EVENT_MULTIPLIER + ")" + ")";
return criticalEventExpression;
}
/**
* Listener method called when Esper has detected a pattern match.
*/
public void update(Map eventMap) {
// 1st Temperature in the Critical Sequence
TemperatureEvent temp1 =
(TemperatureEvent) eventMap.get("temp1");
// 2nd Temperature in the Critical Sequence
TemperatureEvent temp2 =
(TemperatureEvent) eventMap.get("temp2");
// 3rd Temperature in the Critical Sequence
TemperatureEvent temp3 =
(TemperatureEvent) eventMap.get("temp3");
// 4th Temperature in the Critical Sequence
TemperatureEvent temp4 =
(TemperatureEvent) eventMap.get("temp4");
StringBuilder sb = new StringBuilder();
sb.append("***************************************");
sb.append("n* [ALERT] : CRITICAL EVENT DETECTED! ");
sb.append("n* " + temp1 + " > " + temp2 +
" > " + temp3 + " > " + temp4);
sb.append("n***************************************");
LOG.debug(sb.toString());
}
}
运行演示的完整说明可以在这里找到:
这里有两个GitHub代码,它们在Esper的部分是一样的,区别在于,第一个使用一个POJO类产生Esper消息,比较简单。第二个在第一个地基础之上做了拓展,增加了JMS和Apache ActiveMQ。也就是使用JMS来产生Esper消息。如果要顺利执行第二个代码,需要额外安装Apache ActiveMQ。具体情况请阅读每一个项目地README文件。
1. github.com/corsoft/esper-demo-nuclear
2. https://github.com/liangyihuai/Esper4SpingJMS
运行演示的一个例子如下所示 - 它生成随机温度事件并通过Esper处理器发送它们。
当我们的3个查询中的任何一个检测到匹配时 - 调试信息被显示到控制台。在现实世界的解决方案中,这三个监听器中的每一个都会以不同的方式处理这些事件 - 也许可以通过发送消息来提醒队列/端点来获取系统的其他部分来获取处理。
使用像Esper这样的系统是一种使用最少代码实时监控和识别数据模式的简便方法。
这篇文章只是一个简单的用例。查看 Esper网站获取更多信息。
这篇文章翻译自:complex-event-processing-made