Flink超时数据提取

package com.xicent.flink.cep;

import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.java.functions.KeySelector;
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.functions.PatternProcessFunction;
import org.apache.flink.cep.functions.TimedOutPartialMatchHandler;
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.DataStream;
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.Collector;
import org.apache.flink.util.OutputTag;

import java.time.Duration;
import java.util.List;
import java.util.Map;

public class CepDemo {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
        env.enableCheckpointing(1000);

        //输入数据,提取事件时间
        KeyedStream<LoginEvent, Integer> loginEventKeyedStream = env.fromElements(
                new LoginEvent(1, "success", 1575600181000L),
                new LoginEvent(2, "fail1", 1575600182000L),
                new LoginEvent(2, "fail2", 1575600183000L),
                new LoginEvent(3, "fail1", 1575600184000L),
                new LoginEvent(3, "fail2", 1575600189000L)
        ).assignTimestampsAndWatermarks(
                //注册watermark方法和旧版稍有不同
                WatermarkStrategy.<LoginEvent>forBoundedOutOfOrderness(Duration.ofSeconds(0))
                        .withTimestampAssigner((event,timestamp)-> event.getEventTime()))
                .keyBy(new KeySelector<LoginEvent, Integer>() {
            @Override
            public Integer getKey(LoginEvent loginEvent) throws Exception {
                return loginEvent.getUserId();
            }
        });

        //定义Pattern
        Pattern<LoginEvent, LoginEvent> pattern = Pattern.<LoginEvent>begin("begin").where(new SimpleCondition<LoginEvent>() {
            @Override
            public boolean filter(LoginEvent loginEvent) throws Exception {
                return "fail1".equals(loginEvent.getEventType());
            }
        }).<LoginEvent>next("next").where(new SimpleCondition<LoginEvent>() {
            @Override
            public boolean filter(LoginEvent loginEvent) throws Exception {
                return "fail2".equals(loginEvent.getEventType());
            }
        }).within(Time.seconds(5));

        //检测模式
        PatternStream<LoginEvent> patternStream = CEP.pattern(loginEventKeyedStream, pattern);

        //侧输出标志
        OutputTag<LoginEvent> outputTag = new OutputTag<LoginEvent>("timeout") {};

        //process方式提取数据
        SingleOutputStreamOperator<Warning> process = patternStream.process(new MyPatternProcessFunction(outputTag));
        process.print("process login failed twice");
        //提取超时数据
        process.getSideOutput(outputTag).print("process timeout");

        //select方式提取数据
//        SingleOutputStreamOperator<Warning> outputStreamOperator = patternStream
//                .select(
//                        outputTag,
//                        new PatternTimeoutFunction<LoginEvent, LoginEvent>() {
//                    @Override
//                    public LoginEvent timeout(Map<String, List<LoginEvent>> map, long l) throws Exception {
//
//                        return map.get("begin").iterator().next();
//                    }
//                },
//                        new PatternSelectFunction<LoginEvent, Warning>() {
//                    @Override
//                    public Warning select(Map<String, List<LoginEvent>> map) throws Exception {
//                        LoginEvent begin = map.get("begin").iterator().next();
//                        LoginEvent next = map.get("next").iterator().next();
//
//                        return new Warning(begin.getUserId(), begin.getEventTime(), next.getEventTime(), "Login failed twice");
//                    }
//                });

        //提取超时的数据
//        DataStream<LoginEvent> timeoutDataStream = outputStreamOperator.getSideOutput(outputTag);
//        timeoutDataStream.print("timeout");

        //提取匹配数据
//        outputStreamOperator.print("Login failed twice");


        env.execute();
    }


    //TimedOutPartialMatchHandler提供了另外的processTimedOutMatch方法,这个方法对每个超时的部分匹配都会调用。
    static class MyPatternProcessFunction extends PatternProcessFunction<LoginEvent, Warning> implements TimedOutPartialMatchHandler<LoginEvent> {
        private OutputTag<LoginEvent> outputTag;

        public MyPatternProcessFunction(OutputTag<LoginEvent> outputTag) {
            this.outputTag = outputTag;
        }

        @Override
        public void processMatch(Map<String, List<LoginEvent>> map, Context context, Collector<Warning> collector) throws Exception {
            LoginEvent begin = map.get("begin").iterator().next();
            LoginEvent next = map.get("next").iterator().next();

            collector.collect(new Warning(begin.getUserId(), begin.getEventTime(), next.getEventTime(), "Login failed twice"));
        }

        @Override
        public void processTimedOutMatch(Map<String, List<LoginEvent>> map, Context context) throws Exception {
            context.output(outputTag,map.get("begin").iterator().next());
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值