Flink CEP开发流程介绍

FlinkCEP

1.CEP

CEP全称 Complex event processing 复杂事件处理
FlinkCEP 是在 Flink 之上实现的复杂事件处理(CEP)库
擅长高吞吐、低延迟的处理,市场上有多种CEP的解决方案,例如Spark,但是Flink专门类库更方便使用
官网链接:https://ci.apache.org/projects/flink/flink-docs-release-1.13/docs/libs/cep/

2.应用场景

检测和发现无边界事件流中多个记录的关联规则,得到满足规则的复杂事件
允许业务定义要从输入流中提取的复杂模式序列

3.使用流程
  1. 定义pattern
  2. pattern应用到数据流,得到模式流
  3. 从模式流 获取结果
DataStream<Event> input = ...Pattern<Event, ?> pattern = Pattern.<Event>begin("start").where(
        new SimpleCondition<Event>() {
            @Override
            public boolean filter(Event event) {
                return event.getId() == 42;
            }
        }
    ).next("middle").subtype(SubEvent.class).where(
        new SimpleCondition<SubEvent>() {
            @Override
            public boolean filter(SubEvent subEvent) {
                return subEvent.getVolume() >= 10.0;
            }
        }
    ).followedBy("end").where(
         new SimpleCondition<Event>() {
            @Override
            public boolean filter(Event event) {
                return event.getName().equals("end");
            }
         }
    );PatternStream<Event> patternStream = CEP.pattern(input, pattern);DataStream<Alert> result = patternStream.process(
    new PatternProcessFunction<Event, Alert>() {
        @Override
        public void processMatch(
                Map<String, List<Event>> pattern,
                Context ctx,
                Collector<Alert> out) throws Exception {
            out.collect(createAlertFrom(pattern));
        }
    });

CEP并不包含在flink中,使用前需要自己导入

 <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-cep_${scala.version}</artifactId>
            <version>${flink.version}</version>
</dependency>
4.模式(Pattern):定义处理事件的规则
三种模式PatternAPI
  • 个体模式(Individual Patterns)
    组成复杂规则的每一个单独的模式定义
  • 组合模式(Combining Patterns)
    很多个体模式组合起来,形成组合模式
  • 模式组(Groups of Patterns)
    将一个组合模式作为条件嵌套在个体模式里
近邻模式
  • 严格近邻

    期望所有匹配事件严格地一个接一个出现,中间没有任何不匹配的事件, API是.next()

  • 宽松近邻

允许中间出现不匹配的事件,API是.followedBy()

  • 非确定性宽松近邻

    可以忽略已经匹配的条件,API是followedByAny()

  • 指定时间约束

    指定模式在多长时间内匹配有效,API是within

  • 如果您不希望事件类型直接跟随另一个,notNext()

  • 如果您不希望事件类型介于其他两种事件类型之间,notFollowedBy()

模式分类
  • 单次模式
    接收一次一个事件
  • 循环模式
    接收一个或多个事件

其他参数
times:指定固定的循环执行次数
greedy:贪婪模式,尽可能多触发
oneOrMore:指定触发一次或多次
timesOrMore:指定触发固定以上的次数
optional:要么不触发要么触发指定的次数

5.代码示例:
需求:

同个账号,在5秒内连续登录失败2次,则认为存在而已登录问题
数据格式 jack,2021-12-23 10:00:01,-2

public static void main(String[] args) throws Exception {//构建执行任务环境以及任务的启动的入口, 存储全局相关的参数
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
​
        env.setParallelism(1);
​
​
        DataStream<String> ds = env.socketTextStream("127.0.0.1", 8888);
​
​
        DataStream<Tuple3<String, String, Integer>> flatMapDS = ds.flatMap(new FlatMapFunction<String, Tuple3<String, String, Integer>>() {
            @Override
            public void flatMap(String value, Collector<Tuple3<String, String, Integer>> out) throws Exception {
                String[] arr = value.split(",");
                out.collect(Tuple3.of(arr[0], arr[1], Integer.parseInt(arr[2])));
            }
        });
​
​
SingleOutputStreamOperator<Tuple3<String, String, Integer>> watermakerDS = flatMapDS.assignTimestampsAndWatermarks(WatermarkStrategy//延迟策略去掉了延迟时间,时间是单调递增,event中的时间戳充当了水印
                .<Tuple3<String, String, Integer>>forMonotonousTimestamps()
                //生成一个延迟3s的固定水印
                //.<Tuple3<String, String, Integer>>forBoundedOutOfOrderness(Duration.ofSeconds(3))
                .withTimestampAssigner(
                        (event, timestamp) -> {
                            //指定POJO的事件时间列
                            return TimeUtil.strToDate(event.f1).getTime();
                        }
                ));
​
​
​
        KeyedStream<Tuple3<String, String, Integer>, String> keyedStream = watermakerDS.keyBy(new KeySelector<Tuple3<String, String, Integer>, String>() {
            @Override
            public String getKey(Tuple3<String, String, Integer> value) throws Exception {
                return value.f0;
            }
        });//定义模式
        Pattern<Tuple3<String, String, Integer>, Tuple3<String, String, Integer>> pattern = Pattern
                .<Tuple3<String, String, Integer>>begin("firstTimeLogin").where(new SimpleCondition<Tuple3<String, String, Integer>>() {
                    @Override
                    public boolean filter(Tuple3<String, String, Integer> value) throws Exception {// -2 是登录失败错误码
                        return value.f2 == -2;
                    }
                })//.times(2).within(Time.seconds(10));//不是严格近邻
                .next("secondTimeLogin")
                .where(new SimpleCondition<Tuple3<String, String, Integer>>() {
                    @Override
                    public boolean filter(Tuple3<String, String, Integer> value) throws Exception {
                        return value.f2 == -2;
                    }
                }).within(Time.seconds(5));
​
​
        //匹配检查
        PatternStream<Tuple3<String, String, Integer>> patternStream = CEP.pattern(keyedStream, pattern);SingleOutputStreamOperator<Tuple3<String, String,String>> select = patternStream.select(new PatternSelectFunction<Tuple3<String, String, Integer>, Tuple3<String, String,String>>() {
            @Override
            public Tuple3<String, String,String> select(Map<String, List<Tuple3<String, String, Integer>>> map) throws Exception {Tuple3<String, String, Integer> firstLoginFail =  map.get("firstTimeLogin").get(0);Tuple3<String, String, Integer> secondLoginFail =  map.get("secondTimeLogin").get(0);return Tuple3.of(firstLoginFail.f0,firstLoginFail.f1,secondLoginFail.f1);
            }
        });
​
        select.print("匹配结果");
​
        env.execute("CEP job");
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值