flink-CEP模式
package com.ct.loginfail_detect;
import com.ct.loginfail_detect.beans.LoginEvent;
import com.ct.loginfail_detect.beans.LoginFailWarning;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.cep.CEP;
import org.apache.flink.cep.PatternSelectFunction;
import org.apache.flink.cep.PatternStream;
import org.apache.flink.cep.pattern.Pattern;
import org.apache.flink.cep.pattern.conditions.SimpleCondition;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor;
import org.apache.flink.streaming.api.windowing.time.Time;
import java.net.URL;
import java.util.List;
import java.util.Map;
/**
* @Author: liuyi
* @createTime: 2021-06-17 17:06:36
* @Description: cep
*/
public class LoginFailWithCep {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
//数据
URL resource = LoginFailWithCep.class.getResource("/LoginLog.csv");
DataStreamSource<String> inputStream = env.readTextFile(resource.getPath());
// inputStream.print("1处输出"); //ok
//POJO包装 & waterMark
SingleOutputStreamOperator<LoginEvent> dataStream = inputStream.map(new MapFunction<String, LoginEvent>() {
@Override
public LoginEvent map(String s) throws Exception {
String[] splits = s.split(",");
return new LoginEvent(new Long(splits[0]), splits[1], splits[2], new Long(splits[3]));
}
})
// .setBufferTimeout(new Long("10"))//设置超时步长返组
.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<LoginEvent>(Time.seconds(5)) {//
@Override
public long extractTimestamp(LoginEvent loginEvent) {
return loginEvent.getTimestamp() * 1000L;
}
});
// loginEventStream.print("2处输出?");//已经包装好了ok
//cep处理
//1.需要先定义一个匹配模式(目前需要的的模式:firstFail ->secondFail & within 2S)
Pattern<LoginEvent, LoginEvent> loginFailPattern = Pattern
.<LoginEvent>begin("firstFail").where(new SimpleCondition<LoginEvent>() {
@Override
public boolean filter(LoginEvent loginEvent) throws Exception {
return "fail".equals(loginEvent.getLoginState());
}
})
.next("secondFail").where(new SimpleCondition<LoginEvent>() {
@Override
public boolean filter(LoginEvent loginEvent) throws Exception {
return "fail".equals(loginEvent.getLoginState());
}
})
.within(Time.seconds(3))
;
//2.将匹配模式应用到数据流上,得到一个pattern stream
PatternStream<LoginEvent> patternStream = CEP.pattern(dataStream.keyBy(LoginEvent::getUserId), loginFailPattern);
//3.检出符合匹配的复杂事件,进行转换处理,得到报警信息
SingleOutputStreamOperator<LoginFailWarning> warningStream = patternStream.select(new LoginFailMatchDetectWarning());
warningStream.print("login attention >>>>>>>");
env.execute("login fail detect with cep job!");
}
public static class LoginFailMatchDetectWarning implements PatternSelectFunction<LoginEvent, LoginFailWarning>{
@Override
public LoginFailWarning select(Map<String, List<LoginEvent>> map) throws Exception {
// LoginEvent firstFailEvent =map.get("firstFail").get(0);
LoginEvent firstFailEvent =map.get("firstFail").iterator().next();
LoginEvent secondFailEvent =map.get("secondFail").get(0);
return new LoginFailWarning(
firstFailEvent.getUserId(),
firstFailEvent.getTimestamp(),
secondFailEvent.getTimestamp(),
"login failed 2 times!!");
}
}
}