前一部分内容转载自其他文章
watermark生成
watermark的生成策略有两种:一种是周期性生成,另外一种是根据特定标记生成。在实际使用中大多数情况下会选择周期性生成方式也就是AssignerWithPeriodicWatermarks方式,使用方式如下:
// An highlighted block
//指定为evenTime时间语义
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
//生成watermark的周期
env.getConfig.setAutoWatermarkInterval(watermarkInterval)
//指定方式
dataStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor[Element](Time.seconds(allowDealy)) {
override def extractTimestamp(element: Element): Long = element.dT
})
BoundedOutOfOrdernessTimestampExtractor 是Flink内置提供的允许乱序最大延时的watermark生成方式,只需要重写其extractTimestamp方法即可。
assignTimestampsAndWatermarks 可以理解为是一个算子转换操作,等同于map/window一样理解,可以为其设置并行度、名称,也是一个transformation/operator,
// An highlighted block
public SingleOutputStreamOperator<T> assignTimestampsAndWatermarks(
AssignerWithPeriodicWatermarks<T> timestampAndWatermarkAssigner) {
final int inputParallelism = getTransformation().getParallelism();
final AssignerWithPeriodicWatermarks<T> cleanedAssigner = clean(timestampAndWatermarkAssigner);
TimestampsAndPeriodicWatermarksOperator<T> operator =
new TimestampsAndPeriodicWatermarksOperator<>(cleanedAssigner);
return transform("Timestamps/Watermarks", getTransformation().getOutputType(), operator)
.setParallelism(inputParallelism);
}
在生成的jobGraph中,也是作为其中的一部分:
默认的名称就是 Timestamps/Watermarks。
接下来深入分析其使用的StreamOperator类型TimestampsAndPeriodicWatermarksOperator,其继承了AbstractUdfStreamOperator,实现了OneInputStreamOperator接口与ProcessingTimeCallback接口,具体包含的方法:
open方法:
// An highlighted block
public void open() throws Exception {
super.open();
//初始化默认当前watermark
currentWatermark = Long.MIN_VALUE;
//生成watermark周期时间配置
watermarkInterval = getExecutionConfig().getAutoWatermarkInterval();
//注册定时其配置
if (watermarkInterval > 0) {
long now = getProcessingTimeService().getCurrentProcessingTime();
getProcessingTimeService().registerTimer(now + watermarkInterval, this);
}
}
最重要的就是getProcessingTimeService().registerTimer
注册一个watermarkInterval后触发的定时器,传入回调参数是this,也就是会调用当前对象的onProcessingTime方法(关于这部分知识可以查看Flink的定时系列)。
processElement方法:
// An highlighted block
public void processElement(StreamRecord<T> element) throws Exception