Esper 參考
翻譯自:Esper Version 7.1.0 參考手冊,詳情可以查詢:EsperTech Inc. (http://www.espertech.com)
Author:saillen
第一章 起始
1.1 複雜事件處理(CEP)簡介
Esper引擎被應用程序用來分析和處理事件。它的一些典型應用場景如下:
- 業務流程管理和自動化處理(處理監控事件、BAM、報告一些異常等);
- 金融領域:交易行爲、欺詐檢測、風險控制;
- 網絡和應用監控:入侵檢測、SLA監測;
- 基於傳感器的應用:RFID應用、航空管制、製造業流水線的調度、管理;
這些應用場景中有一些共同的需求就是需要實時或者近實時的處理事件或者消息。這種處理方式被稱爲複雜事件處理
、系列事件分析
。這些場景都需要考慮的一些共有問題:吞吐量
、延遲性
和複雜的邏輯處理
;
- 高吞吐量:應用需要在短時間內處理大量事件(需要具備每秒1000到100K的消息處理能力);
- 低延遲:應用需要在短時間內給出響應結果;
- 複雜的計算邏輯:應用程序需要在事件間檢測模式(檢測事件的相關性),過濾不必要的事件,在事件上做一些基於時間、長度的聚合統計等。
Esper引擎的設計目標就是:可以很容易的構建一個CEP應用。
更多的關於CEP的信息可以參考:http://www.espertech.com/esper/esperfaq#whatiscep
1.2 HelloWord工程
1.2.1 第一步:設置Classpath;
如果不使用Maven的話,需要將Esper和它依賴的jar文件加入到classpath中,這些jar包需要自行下載:
- Esper 核心jra包: esper-version.jar;
- ANTLR 分析用jar包:antlr-runtime-4.7.jar;
- CGLIB 代碼產生jar包:cglib-nodep-3.2.5.jar;
- SFG4J 日誌哭:slf4j-api.1.7.25.jar;
- Janino Java編譯器:janino-3.0.7.jar 和 commons-compiler-3.0.7.jar
如果你的項目想使用Log4j作爲日誌框架,可以添加slf4j-log3jl2-1.2.25.jar
和 log4j-1.2.17.jar
相關包。
如果你還需要使用Apache的Avro
,可以添加 epser-avro-version.jar
。
如果你使用Maven的話,可以加入如下的Maven依賴:
<dependency>
<groupId>com.espertech</groupId>
<artifactId>esper</artifactId>
<version>7.1.0</version>
</dependency>
1.2.2 第二步:獲取引擎實例
在應用中可以通過調用EPServiceProvierManager
類的靜態方法:getDefaultProvier
獲取一個引擎實例。
EPServiceProvider engine = EPServiceProviderManager.getDefaultProvider();
上面的示例中沒有使用配置對象,這樣引擎會使用默認配置。引擎默認的URI配置爲:default
。
PS : 這裏提到的URI可以先忽略,真正Esper使用的時候,會使用Configuration對象配置下事件的命名空間等概念。
1.2.3 第三步:爲輸入事件(Input Event)提供信息;
獲取引擎instance後需要向引擎註冊一個Event Type
,Evenet Type
用來告訴引擎一個Event
的數據結構是什麼樣的。當創建一個EPL
語句後,引擎會檢查註冊過的Event Type
,然後選擇一個合適的類型來表示事件的數據結構。
下面的例子使用的是Java類再來定義Event Type
。PersonEvent
類表示的是事件類型(即事件具有的屬性和結構),每個PersonEvent
的實例表示的具體的事件。Esper不要求每個Event Type
都創建一個java類,它支持多種數據結構。具體使用哪種數據結構可以根據自己的應用的實際情況來決定。
package com.saillen.esper.demo;
public class PersonEvent{
private String name;
private int age;
public PersonEvent(String name, int age){
this.name = name;
this.age = age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
在程序裏面可以通過調用Configuration
對象的 addEventType
方法來註冊一個Event Type
,這個方法是一個運行時配置接口的方法。
engine.getEpAdministrator().getConfiguration().addEventType(PersonEvent.class);
通過調用addEventType
方法來告訴引擎Event type
,引擎基於java的反射API會自動分析事件的屬性信息。比如上面的代碼,我們告訴引擎事件類型爲PersonEvent
。PersonEvent
有兩個符合JavaBean標準的getter
方法。這樣引擎就知道,PersonEvent
有兩個屬性:一個string
類型的name
屬性,一個int
類型的age
屬性。
現在,引擎已經知道了有一個 PersonEvent
類型的事件,然後在應用程序中就可以創建EPL
語句給引擎,然後EPL
就可以使用到事件的屬性信息。
除了可以定義Java Class
類型的事件Type外,Esper還支持使用Apache Avro
模式或者XML
格式、Map
、屬性名數組
的方式來定義event type
。
定義event type是用過 Configuration
對象完成的,除了可以調用api接口,還可以使用 EPL語句,類似:create schema
的方式。
1.2.4 第四步:創建EPL語句並且添加回調
在起始章節,一個EPL
語句非常簡單,僅僅用來查詢每個person event中的name和age屬性,eg:
select name,age from PersonEvent
在應用程序中可以通過administrative
接口的createEPL
方法來創建一個EPL statement。
String epl = "select name , age from PersonEvent";
EPStatement statement = engine.getEPAdministrator().createEPL(epl);
上面調用createEPL
方法後,引擎會校驗from
子句中出現的PersonEvent
是否存在,引擎還會校驗select
子句中出現的 name
和age
屬性在PersonEvent
中是否存在。
當引擎校驗成功後,引擎會向內部維護的一個 filter index tree
(基於索引結構的過濾樹?)添加一個對象,這個tree結構的對象會保證每個Person Event
來的時候會被這個statement
處理。
應用程序中也可以添加一個EPStatement
的回調,這個回調用來接收語句的處理結果,類似如下:
//這裏用的是JDK 8的lamad表達式,實際上就是一個UpdateListener接口的匿名實現。
statement.addListener( (newData,oldData) -> {
String name = (String)newData[0].get("name");
int age = newData[0].get("age");
System.out.pritnln(String.format("Name: %s, Age : %d",name, age));
} )
PS: EPL語句其實就是Esper定義的一種事件處理規則類似Sql語句,statement可以作爲Esper的一個術語看待,Esper的參考文檔第二章專門講述了Esper語句裏面的各種概念,使用Esper的核心有很大一部分就是寫EPL語句。
1.2.5 第五步:發送事件(Events)
在應用程序中可以通過sendEvent
方法來發送一個事件:
engine.getEpRuntime().sendEvent(new PersonEvent("Peter",10));
然後你的程序會看見如下的輸入內容:
Name: Peter, Age:10
當調用sendEvent
發送事件的時候,引擎會詢問內部維護的 filter index tree
,來決定是否有EPL statement
對這個事件感興趣。EPL語句作爲Person事件的一部分,引擎會把這個event
委託給statement
處理。EPL statement
通過調用getName
和getAge
方法來獲取name
、age
屬性。
最後,下面是完整的事件處理代碼:
EPServiceProvider engine = EPServiceProvierManager.getDefaultProvider();
engein.getEPAdministraotr().getConfiguration().addEventType(PersonEvent.class);
String epl = " select name, age from PersonEvent ";
EPStatement statement = engine.getEPAdministrator().createEPL(epl);
statement.addListener( (newData,oldData)-> {
String name = (String)newData[0].get("name");
int age = (int) newData[0].get("age");
System.out.println(String.format("Name: %s, Age: %d",name,age));
});
engine.getEPRuntime().sendEvent(new PersonEvent("Peter",10));
1.3 需要的第三方庫
Esper需要下面的第三方庫來支撐它的運行:
- ANTLR:全稱ANother Tool for Language Recognition,是一種語言識別工具,Esper用它來解析EPL語句;
- CGLIB:用來織入二進制代碼的工具,Esper爲了提升處理效率會產生很多高校的class;
- SLF4J:日誌框架,可以和Log4j一起工作,slf4j僅僅是一個門面,不影響具體日誌框架的選擇;
- Janino:一個小巧快速的java編譯器,Esper爲了提升效率,使用janino來快速的產生、編譯代碼。