// 1. 定义一个匹配模式
val orderPayPattern = Pattern.begin[OrderEvent]("begin").where(_.eventType == "create")
.followedBy("follow").where(_.eventType == "pay")
.within(Time.minutes(15))
// 2. 把模式应用到stream上,得到一个pattern stream
val patternStream = CEP.pattern(orderEventStream, orderPayPattern)
// 3. 调用select方法,提取事件序列,超时的事件要做报警提示
val orderTimeoutOutputTag = new OutputTag[OrderResult]("orderTimeout")
val resultStream = patternStream.select(orderTimeoutOutputTag,
new OrderTimeoutSelect(),
new OrderPaySelect())
.followedBy("follow").where(_.eventType == "pay")
val orderPayPattern = Pattern.begin[OrderEvent]("begin").where(_.eventType == "create")
val orderPayPattern = Pattern.begin[OrderEvent]("begin").where(_.eventType == "create")
.followedBy("follow").where(_.eventType == "pay")
.within(Time.minutes(15))
个体模式可以包括"单例(sigleton)模式"和"循环(looping)模式",单例模式只能接收一个时间,而循环模式可以接收多个
可以在一个个体模式后追加量词,也就是指定循环次数
//匹配出现4次
start.times(4)
//匹配出现2/3/4次
start.time(2,4).greedy
//匹配出现0或者4次
start.times(4).optional
//匹配出现1次或者多次
start.oneOrMore
//匹配出现2,3,4次
start.times(2,4)
//匹配出现0次,2次或者多次,并且尽可能多的重复匹配
start.timesOrMore(2),optional.greedy
Pattern.begin[OrderEvent]("begin").where(_.eventType == "create")
pattern.where(event=>.../*some condition */).or(event=>.../*or condition */)
如果使用了oneOrMore或者oneOrMore.optional,建议使用.until()作为终止条件,以便清理状态
能够对模式之前所有接收的时间进行处理;
调用.where((value,ctx)=>{…}),可以调用ctx.getEventsForPattern(“name”)
注意:
val orderEventStream = env.socketTextStream("localhost", 7777)
.map(data => {
val dataArray = data.split(",")
OrderEvent(dataArray(0).trim.toLong, dataArray(1).trim, dataArray(2).trim, dataArray(3).trim.toLong)
})
.assignAscendingTimestamps(_.eventTime * 1000L)
.keyBy(_.orderId)
// 2. 定义一个匹配模式
val orderPayPattern = Pattern.begin[OrderEvent]("begin").where(_.eventType == "create")
.followedBy("follow").where(_.eventType == "pay")
.within(Time.minutes(15))
// 3. 把模式应用到stream上,得到一个pattern stream
val patternStream = CEP.pattern(orderEventStream, orderPayPattern)
def delectFn(pattern :Map[String,Iterable[IN]]):OUT={
val startEvent=pattern.get("start").get.next
val endEcent=pattern.get("end").get.next
OUT(startEvent,endEvent)
}
// 定义输入订单事件的样例类
case class OrderEvent(orderId: Long, eventType: String, txId: String, eventTime: Long)
// 定义输出结果样例类
case class OrderResult(orderId: Long, resultMsg: String)
object OrderTimeout {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
env.setParallelism(1)
// 1. 读取订单数据
val resource = getClass.getResource("/OrderLog.csv")
// val orderEventStream = env.readTextFile(resource.getPath)
val orderEventStream = env.socketTextStream("localhost", 7777)
.map(data => {
val dataArray = data.split(",")
OrderEvent(dataArray(0).trim.toLong, dataArray(1).trim, dataArray(2).trim, dataArray(3).trim.toLong)
})
.assignAscendingTimestamps(_.eventTime * 1000L)
.keyBy(_.orderId)
// 2. 定义一个匹配模式
val orderPayPattern = Pattern.begin[OrderEvent]("begin").where(_.eventType == "create")
.followedBy("follow").where(_.eventType == "pay")
.within(Time.minutes(15))
// 3. 把模式应用到stream上,得到一个pattern stream
val patternStream = CEP.pattern(orderEventStream, orderPayPattern)
// 4. 调用select方法,提取事件序列,超时的事件要做报警提示
val orderTimeoutOutputTag = new OutputTag[OrderResult]("orderTimeout")
val resultStream = patternStream.select(orderTimeoutOutputTag,
new OrderTimeoutSelect(),
new OrderPaySelect())
resultStream.print("payed")
resultStream.getSideOutput(orderTimeoutOutputTag).print("timeout")
env.execute("order timeout job")
}
}
// 自定义超时事件序列处理函数
class OrderTimeoutSelect() extends PatternTimeoutFunction[OrderEvent, OrderResult] {
override def timeout(map: util.Map[String, util.List[OrderEvent]], l: Long): OrderResult = {
val timeoutOrderId = map.get("begin").iterator().next().orderId
OrderResult(timeoutOrderId, "timeout")
}
}
// 自定义正常支付事件序列处理函数
class OrderPaySelect() extends PatternSelectFunction[OrderEvent, OrderResult] {
override def select(map: util.Map[String, util.List[OrderEvent]]): OrderResult = {
val payedOrderId = map.get("follow").iterator().next().orderId
OrderResult(payedOrderId, "payed successfully")
}
}