一、CEP案例:超时未支付
### --- CEP案例:超时未支付
~~~ 案例3:超时未支付
~~~ 需求:找出下单后10分钟没有支付的订单
二、实现思路:
### --- 1、数据源:
new PayEvent(1L, "create", 1597905234000L),
new PayEvent(1L, "pay", 1597905235000L),
new PayEvent(2L, "create", 1597905236000L),
new PayEvent(2L, "pay", 1597905237000L),
new PayEvent(3L, "create", 1597905239000L)
### --- 2、转化watermark
### --- 3、keyby转化
### --- 4、做出Pattern(下单以后10分钟内未支付)
~~~ 注意:下单为create 支付为pay ,create和pay之间不需要是严格临近,所以选择followedBy
Pattern<PayEvent, PayEvent> pattern = Pattern.<PayEvent>begin("begin")
.where(new IterativeCondition<PayEvent>() {
@Override
public boolean filter(PayEvent payEvent, Context context)
throws Exception {
return payEvent.getName().equals("create");
}
})
.followedBy("pay")
.where(new IterativeCondition<PayEvent>() {
@Override
public boolean filter(PayEvent payEvent, Context context)
throws Exception {
return payEvent.getName().equals("pay");
}
})
.within(Time.seconds(600));
### --- 5、模式匹配
### --- 6、取出匹配成功的数据
~~~ 采用测输出的方式
OutputTag<PayEvent> orderTimeoutOutput = new OutputTag<PayEvent>("orderTimeout"){};
~~~ # 采用select方法
SingleOutputStreamOperator<PayEvent> result =
patternStream.select(orderTimeoutOutput, new PatternTimeoutFunction<PayEvent,
PayEvent>() {
@Override
public PayEvent timeout(Map<String, List<PayEvent>> map, long l)
throws Exception {
return map.get("begin").get(0);
}
}, new PatternSelectFunction<PayEvent, PayEvent>() {
@Override
public PayEvent select(Map<String, List<PayEvent>> map) throws
Exception {
return map.get("pay").get(0);
}
});
//result.print();
DataStream<PayEvent> sideOutput =
result.getSideOutput(orderTimeoutOutput);
sideOutput.print();
三、编程代码实现
### --- 编程代码实现
package com.yanqi.mycep;
import org.apache.flink.api.common.eventtime.*;
import org.apache.flink.cep.CEP;
import org.apache.flink.cep.PatternSelectFunction;
import org.apache.flink.cep.PatternStream;
import org.apache.flink.cep.PatternTimeoutFunction;
import org.apache.flink.cep.pattern.Pattern;
import org.apache.flink.cep.pattern.conditions.IterativeCondition;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.util.OutputTag;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
public class PayDemo {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
env.setParallelism(1);
DataStreamSource<PayBean> data = env.fromElements(
new PayBean(1L, "create", 1597905234000L),
new PayBean(1L, "pay", 1597905235000L),
new PayBean(2L, "create", 1597905236000L),
new PayBean(2L, "pay", 1597905237000L),
new PayBean(3L, "create", 1597905239000L)
);
SingleOutputStreamOperator<PayBean> watermarks = data.assignTimestampsAndWatermarks(new WatermarkStrategy<PayBean>() {
@Override
public WatermarkGenerator<PayBean> createWatermarkGenerator(WatermarkGeneratorSupplier.Context context) {
return new WatermarkGenerator<PayBean>() {
long maxTimeStamp = Long.MIN_VALUE;
long maxOutOfOrderness = 500l;
@Override
public void onEvent(PayBean event, long eventTimestamp, WatermarkOutput output) {
maxTimeStamp = Math.max(maxTimeStamp, event.getTs());
}
@Override
public void onPeriodicEmit(WatermarkOutput output) {
output.emitWatermark(new Watermark(maxTimeStamp - maxOutOfOrderness));
}
};
}
}.withTimestampAssigner((element, recordTimestamp) -> element.getTs()));
KeyedS