Flink的定时器(EventTime和ProcessTime)

Flink定时器
1、Flink当中定时器Timer的基本用法
定时器Timer是Flink提供的用于感知并利用处理时间、事件事件变化的一种机制,通常在KeyedProcessFunction当中使用定时器Timer,具体步骤:
在processElement()方法当中注册Timer,然后通过重写onTimer()方法作为Timer定时器出发时的回调逻辑。
2、简述在Flink当中注册定时器Timer的俩种方法
方式1:通过调用
Context.timerService().registerProcessTimeTimer()注册定时器,定时器在系统时间达到设定的时间戳时出发;
方式2:通过调用
Context.timerService().registerEventTimeTimer()方法注册定时器,定时器在Flink内部水印达到或者超过Timer设定的时间戳时出发。

eventTimer案列demo:

package Flink_API;

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.java.tuple.Tuple;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;
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.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.KeyedProcessFunction;
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010;
import org.apache.flink.streaming.util.serialization.DeserializationSchema;
import org.apache.flink.util.Collector;

import java.text.SimpleDateFormat;
import java.util.Properties;

public class TestEventTimer {
    public static void main(String[] args) throws Exception {
        //获取Flink的运行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
        env.setParallelism(1);

        String topic="test_topi_2";
        Properties properties=new Properties();
        properties.setProperty("bootstrap.servers","page1:9002");
        properties.setProperty("group.id","con1");

        FlinkKafkaConsumer010 myConsumer =new  FlinkKafkaConsumer010<>(topic, (DeserializationSchema) new SimpleStringSchema(),properties);
        DataStreamSource kafkaTestStream = env.addSource(myConsumer);
        DataStream StreamOperator=kafkaTestStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(30)) {
            @Override
            public long extractTimestamp(String s) {
                String[] splited =s.split(",");
                long event_time=Long.parseLong(splited[1]);
                return event_time;
            }
        });
        DataStream> stream=StreamOperator.flatMap(new FlatMapFunction>() {
            @Override
            public void flatMap(String s, Collector> collector) throws Exception {
                String[] splited = s.split("\\W+");
                collector.collect(Tuple2.of(splited[0],1));
            }
        }).setParallelism(5);

        stream.keyBy(0).process(new CountWithTimeoutFunction());
        env.execute("TestEventTimer");

    }
    public static class CountWithTimestamp{
        public String key;
        public Integer count;
        public long lastModified;

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public Integer getCount() {
            return count;
        }

        public void setCount(Integer count) {
            this.count = count;
        }

        public long getLastModified() {
            return lastModified;
        }

        public void setLastModified(long lastModified) {
            this.lastModified = lastModified;
        }

        @Override
        public String toString() {
            return "CountWithTimestamp{" +
                    "key='" + key + '\'' +
                    ", count=" + count +
                    ", lastModified=" + lastModified +
                    '}';
        }
    }
    //eventTime的定时器
    public static class CountWithTimeoutFunction extends KeyedProcessFunction,Tuple2> {
        private ValueState state;

        @Override
        public void open(Configuration parameters) throws Exception {
            super.open(parameters);
            state = getRuntimeContext().getState(new ValueStateDescriptor<>("myState",CountWithTimestamp.class));
        }

        @Override
        public void processElement(Tuple2 value, Context context, Collector> collector) throws Exception {
            CountWithTimestamp current = state.value();
            if(current == null){
                current = new CountWithTimestamp();
                current.key=value.f0;
                current.count = 0;
                current.lastModified = 0;
            }

            current.count +=1;
            current.lastModified=context.timestamp();
            state.update(current);

            context.timerService().registerEventTimeTimer(current.lastModified + 60000);
        }

        /**
         * 定时器出发时的回调函数
         * @param timestamp 定时器设定的时间,注意:不是watermark的时间。
         * @param ctx
         * @param out
         * @throws Exception
         */
        @Override
        public void onTimer(long timestamp, OnTimerContext ctx, Collector> out) throws Exception {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
            System.out.print("====>定时器:"+sdf.format(timestamp)+"被处罚!处罚时的watermark是:"+ctx.timerService().currentWatermark());
            CountWithTimestamp result = state.value();
            if(timestamp == result.lastModified + 60000){
                out.collect(Tuple2.of(result.key,result.count));
            }

        }
    }

}

processTimer的案例:一个商品在100秒之内连续上升,就会输出这个商品

 

package Flink_API;

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.java.tuple.Tuple;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;
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.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.KeyedProcessFunction;
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010;
import org.apache.flink.streaming.util.serialization.DeserializationSchema;
import org.apache.flink.util.Collector;

import java.text.SimpleDateFormat;
import java.util.Properties;

public class TestEventTimer {
    public static void main(String[] args) throws Exception {
        //获取Flink的运行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
        env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime);
        env.setParallelism(1);

        String topic="test_topi_2";
        Properties properties=new Properties();
        properties.setProperty("bootstrap.servers","page1:9002");
        properties.setProperty("group.id","con1");

        FlinkKafkaConsumer010 myConsumer =new  FlinkKafkaConsumer010<>(topic, (DeserializationSchema) new SimpleStringSchema(),properties);
        DataStreamSource kafkaTestStream = env.addSource(myConsumer);
        DataStream StreamOperator=kafkaTestStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(30)) {
            @Override
            public long extractTimestamp(String s) {
                String[] splited =s.split(",");
                long event_time=Long.parseLong(splited[1]);
                return event_time;
            }
        });
        DataStream> stream=StreamOperator.flatMap(new FlatMapFunction>() {
            @Override
            public void flatMap(String s, Collector> collector) throws Exception {
                String[] splited = s.split("\\W+");
                collector.collect(Tuple2.of(splited[0],1));
            }
        }).setParallelism(5);

        stream.keyBy(0).process(new TempIncreWaring(10000)).print();
        env.execute("TestProcessTimer");

    }
    public static class CountWithTimestamp{
        public String key;
        public Integer count;
        public long lastModified;

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public Integer getCount() {
            return count;
        }

        public void setCount(Integer count) {
            this.count = count;
        }

        public long getLastModified() {
            return lastModified;
        }

        public void setLastModified(long lastModified) {
            this.lastModified = lastModified;
        }

        @Override
        public String toString() {
            return "CountWithTimestamp{" +
                    "key='" + key + '\'' +
                    ", count=" + count +
                    ", lastModified=" + lastModified +
                    '}';
        }
    }

    //processTime的定时器
    public static class TempIncreWaring extends KeyedProcessFunction,String>{
        private Integer intervalTime;
        public TempIncreWaring(Integer intervalTime){
            this.intervalTime=intervalTime;
        }
        //定义状态:保存该key对应的上一个价格值进行比较,保存注册定时器时间戳用于删除
        private ValueState lastPriceState;
        private ValueState timerTsState;

        @Override
        public void open(Configuration parameters) throws Exception {
            super.open(parameters);
            lastPriceState=getRuntimeContext().getState(new ValueStateDescriptor<>("myState1",Integer.class,0));
            timerTsState=getRuntimeContext().getState(new ValueStateDescriptor<>("myState2",Long.class,0L));
        }

        @Override
        public void processElement(Tuple2 value, Context context, Collector collector) throws Exception {
            Integer lastPrice = lastPriceState.value();
            long timerTs = timerTsState.value();

            //当前价格和上一次价格进行比较
            if(value.f1 > lastPrice && timerTs == 0L){
                long ts =context.timerService().currentProcessingTime() + this.intervalTime;
                context.timerService().registerProcessingTimeTimer(ts);
                //更新定时器时间
                timerTsState.update(ts);
            }else if(value.f1 <= lastPrice){
                //如果价格下降,删除定时器
                context.timerService().deleteProcessingTimeTimer(timerTs);
                timerTsState.update(0L);//或者timerTsState.clear()
            }
            lastPriceState.update(value.f1);

        }

        @Override
        public void onTimer(long timestamp, OnTimerContext ctx, Collector out) throws Exception {
            System.out.print("------------>");
            out.collect("商品:"+ctx.getCurrentKey()+"的价格,连续:"+this.intervalTime/1000+"秒连续上升");
            timerTsState.clear();//定时器清零
            System.out.print("<--------------------");
        }
    }
}

你可能感兴趣的:(【Flink】,flink,大数据,big,data)