Flink 使用watermark

自定义一个watermark生成策略

watermark生成策略一般有两种,一种是自定义周期性的watermark,另一种是触发式的watermark。
WatermarkGenerator接口代码如下:

@Public
public interface WatermarkGenerator<T> {

    /**
     * 每来一条事件数据调用一次,可以检查或者记录事件的时间戳,或者也可以基于事件数据本身去生成 watermark。
     */
    void onEvent(T event, long eventTimestamp, WatermarkOutput output);

    /**
     * 周期性的调用,也许会生成新的 watermark,也许不会。
     *
     * 

调用此方法生成 watermark 的间隔时间由 {@link ExecutionConfig#getAutoWatermarkInterval()} 决定。 * env.getConfig.getAutoWatermarkInterval(); *

可以通过 env.getConfig.getAutoWatermarkInterval() 设置触发间隔 */ void onPeriodicEmit(WatermarkOutput output); }

自定义watermark

package org.example.watermark;

import org.apache.flink.api.common.eventtime.Watermark;
import org.apache.flink.api.common.eventtime.WatermarkGenerator;
import org.apache.flink.api.common.eventtime.WatermarkOutput;

public class MyStrategy implements WatermarkGenerator<Integer> {
    long cur;
    @Override
    public void onEvent(Integer integer, long l, WatermarkOutput watermarkOutput) {
        // 每来一条数据即更新一下当前的event-time
        cur = Math.max(cur, l);
    }

    @Override
    public void onPeriodicEmit(WatermarkOutput watermarkOutput) {
    	// 触发生成新的watermark
        System.out.println("生成新的watermark: " + cur);
        watermarkOutput.emitWatermark(new Watermark(cur));
    }
}

使用watermark

package org.example.watermark;

import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;

public class MyDemo1 {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        env.getConfig().setAutoWatermarkInterval(5000);

        // 1. 输入100,此时watermark是100
        // 2. 再输入3000,此时触发window计算;输出100,watermark是3000
        // 3. 再输入300,此时watermark是3000
        // 4. 再输入6000,此时触发window计算;输出3000,watermark是6000,300已经被丢弃
        DataStream<String> strSource = env.socketTextStream("127.0.0.1", 9000);

        DataStream<Integer> source = strSource.map(Integer::valueOf);

		// 使用自定义的watermark策略
        DataStream<Integer> sourceWithWatermark = source.assignTimestampsAndWatermarks(
                ((WatermarkStrategy<Integer>) context -> new MyStrategy())
                        .withTimestampAssigner((elm, l) -> elm)
        );

        sourceWithWatermark.keyBy(k -> k % 5)
                .window(TumblingEventTimeWindows.of(Time.seconds(3)))
                .reduce(Integer::sum)
                .print();


        env.execute();
    }

}

你可能感兴趣的:(flink)