说到Esper,不得不说一下CEP。CEP,即Complex Event Process,复杂事件处理。实际上,就是基于事件流进行数据处理,把要分析的数据抽象成事件,然后将事件发送到CEP引擎,引擎会根据输入的事件和最初注册的处理器,得到事件处理结果。
CEP是一种标准,Esper只是对这个标准的一种开源实现。除了Esper,很多大公司也有类似的商业软件实现,比如IBM,Sybase等等。CEP的一个重要特点就是他是一个内存计算工具和类SQL语句。好处自不必说,一个字:快!
CEP的类SQL语句,可以理解为处理模型的定义与描述。这是运行在CEP引擎中的特殊语句,之所以叫他类SQL,是因为它和SQL确实很像,除了 select,insert,delete,update,而且也有avg,count等函数。在Esper中,这个句子叫做EPL,即Event Process Language,是Esper的核心内容。
范例:计算每三笔业务的累计数量。
在笔记本(CPU I5-5200U 2.2GHz,Mem 8G)运行1亿次,用时40秒。
--Stock.java
package com.lands.esper;
public class Stock {
private String symbol;
private String side;
private double price;
private long qty;
private String regId;
public final String getSymbol() {
return symbol;
}
public final void setSymbol(String symbol) {
this.symbol = symbol;
}
public final String getSide() {
return side;
}
public final void setSide(String side) {
this.side = side;
}
public final double getPrice() {
return price;
}
public final void setPrice(double price) {
this.price = price;
}
public final long getQty() {
return qty;
}
public final void setQty(long qty) {
this.qty = qty;
}
public final String getRegId() {
return regId;
}
public final void setRegId(String regId) {
this.regId = regId;
}
}
--TotalOrderQtyLimitCheck
package com.lands.esper.test1;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.UpdateListener;
public class TotalOrderQtyLimitCheck implements UpdateListener {
@Override
public void update(EventBean[] newEvents, EventBean[] oldEvents) {
if (newEvents != null) {
Long totalQty = (Long) newEvents[0].get("sum(qty)");
Double avgPrice = (Double) newEvents[0].get("avg(price)");
//System.out.println("totalQty =" + totalQty);
//System.out.println("avgPrice =" + avgPrice);
//System.out.println(newEvents.length);
}
}
}
--OrderRequest.java
package com.lands.esper.test1;
import com.espertech.esper.client.EPRuntime;
import com.lands.esper.Stock;
public class OrderRequest implements Runnable {
EPRuntime runtime = null;
OrderRequest(EPRuntime runtime) {
this.runtime = runtime;
}
@Override
public void run() {
long begin=System.nanoTime();
int i=1;
while(true) {
i++;
Stock order=new Stock();
order.setRegId("liwei");
order.setSide("B");
if (i % 2 == 0) {
order.setSymbol("600000");
order.setQty(200);
order.setPrice(2);
} else {
order.setSymbol("000001");
order.setQty(100);
order.setPrice(1);
}
this.runtime.sendEvent(order);
if (i >= 100000000)
break;
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
long end=System.nanoTime();
System.out.println((end-begin)/1000000);
}
}
--Main.java
package com.lands.esper.test1;
import com.espertech.esper.client.EPAdministrator;
import com.espertech.esper.client.EPRuntime;
import com.espertech.esper.client.EPServiceProvider;
import com.espertech.esper.client.EPServiceProviderManager;
import com.espertech.esper.client.EPStatement;
import com.lands.esper.Stock;
public class Test1 {
public static void main(String[] args) {
EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();
EPAdministrator admin = epService.getEPAdministrator();
String stock = Stock.class.getName();
String epl = "select sum(qty),avg(price) from " + stock + ".win:length_batch(3) where symbol='600000' ";
EPStatement state = admin.createEPL(epl);
state.addListener(new TotalOrderQtyLimitCheck());
EPRuntime runtime = epService.getEPRuntime();
Thread t = new Thread(new OrderRequest(runtime));
t.start();
}
}