Timer timer of flink

1. Introduction to Timer

Timer (Timer) is a mechanism provided by Flink Streaming API to sense and utilize processing time/event time changes.

The most common place to use Timer is KeyedProcessFunction. We register the Timer in its processElement() method, and then override its onTimer() method as the callback logic when the Timer is triggered. According to different time characteristics:

(1) Processing time -call Context.timerService().registerProcessingTimeTimer() to register; onTimer() is triggered when the system timestamp reaches the timestamp set by Timer.
(2) Event time -call Context.timerService().registerEventTimeTimer() to register; onTimer() is triggered when the internal watermark of Flink reaches or exceeds the timestamp set by the Timer.

Two, use demo

The demo function is to use mapState for wordCount and Timer to periodically clear the state every 2 seconds
(1) Program entry

package testOntimer;

import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

/**
 * @程序功能:读取文件,进行wordCount,利用state测试onTimer定时器
 * @author gaoj
 * @Created_in 2020-12-08
 */
public class Driver {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        env
            .addSource(new Source())
            .flatMap(new Map())
            .keyBy(t -> t._1)
            .process(new Process())
            .print();

        env.execute();
    }
}

(2) Program data source

package testOntimer;


import org.apache.commons.lang3.StringUtils;
import org.apache.flink.streaming.api.functions.source.RichSourceFunction;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.concurrent.TimeUnit;

public class Source extends RichSourceFunction<String> {
    private Boolean isRunning = true;
    @Override
    public void run(SourceContext<String> ctx) throws Exception {
        BufferedReader bufferedReader = new BufferedReader(new FileReader("D:\\test.txt"));
        while (isRunning){
            String line = bufferedReader.readLine();
            if(StringUtils.isNotBlank(line)){
                ctx.collect(line);
            }
            TimeUnit.SECONDS.sleep(10);
        }
    }
    @Override
    public void cancel() {
        isRunning = false;
    }
}

(3) Data source conversion

package testOntimer;

import org.apache.flink.api.common.functions.RichFlatMapFunction;
import org.apache.flink.util.Collector;
import scala.Tuple2;

public class Map extends RichFlatMapFunction<String, Tuple2<String,Integer>> {
    @Override
    public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
        String[] split = value.split(",");
        for (String s : split) {
            out.collect(new Tuple2<>(s,1));
        }
    }
}

(4) Perform wordCount

package testOntimer;

import org.apache.flink.api.common.state.MapState;
import org.apache.flink.api.common.state.MapStateDescriptor;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.functions.KeyedProcessFunction;
import org.apache.flink.util.Collector;
import scala.Tuple2;

import java.util.Calendar;


public class Process extends KeyedProcessFunction<String, Tuple2<String,Integer> ,Tuple2<String,Integer>> {
    private transient MapState<String,Integer> mapState;
    private transient ValueState<Integer> valueState;

    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        MapStateDescriptor<String,Integer> mapStateDescriptor = new MapStateDescriptor<>("valueStateDesc",
                TypeInformation.of(new TypeHint<String>() {}),
                TypeInformation.of(new TypeHint<Integer>() {}));
         mapState = getRuntimeContext().getMapState(mapStateDescriptor);


        ValueStateDescriptor<Integer> ValueStateDescriptor = new ValueStateDescriptor<>("phoneCount",
                TypeInformation.of(new TypeHint<Integer>() {
        }));
        valueState=getRuntimeContext().getState(ValueStateDescriptor );
    }

    @Override
    public void processElement(Tuple2<String,Integer> value, Context ctx, Collector<Tuple2<String, Integer>> out) throws Exception {
        if (valueState.value()==null){
           ctx.timerService().registerProcessingTimeTimer(System.currentTimeMillis()+2000);
        }
        int i = mapState.contains(value._1) ? mapState.get(value._1) : 0;
        int i1 = i + 1;
        mapState.put(value._1,i1);
        out.collect(new Tuple2<>(value._1,i1));
    }

    @Override
    public void onTimer(long timestamp, OnTimerContext ctx, Collector<Tuple2<String, Integer>> out) throws Exception {
        mapState.clear();
        valueState.clear();
    }

    @Override
    public void close() throws Exception {
        super.close();
    }
}

Guess you like

Origin blog.csdn.net/qq_44962429/article/details/110875555