Flink 源码学习|WatermarkStrategy

本文详细介绍了ApacheFlink中的WatermarkStrategy接口,如何通过接口实现自定义水印生成策略,包括TimestampAssigner和WatermarkGenerator的配置,以及如何使用lambda表达式和方法覆盖默认行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用事件时间时,需要通过 Flink API 的 WatermarkStrategy 接口配置 watermark 的生成策略。

我们将逐段来看这个 API 的各个部分。

继承关系

WatermarkStrategy 接口继承了 TimestampAssignerSupplierWatermarkGeneratorSupplier,即相当于包含了 TimestampAssignerWatermarkGenerator,具体地:

  • TimestampAssigner 用于从消息记录中提取事件时间戳
  • WatermarkGenerator 用于根据事件时间戳生成 watermark

源码flink-core/src/main/java/org/apache/flink/api/common/eventtime/WatermarkStrategy.java#L19Github

package org.apache.flink.api.common.eventtime;

import org.apache.flink.annotation.Public;
import org.apache.flink.annotation.PublicEvolving;

import java.io.Serializable;
import java.time.Duration;

import static org.apache.flink.util.Preconditions.checkArgument;
import static org.apache.flink.util.Preconditions.checkNotNull;

@Public
public interface WatermarkStrategy<T>
     extends TimestampAssignerSupplier<T>, WatermarkGeneratorSupplier<T> {

其中,泛型 T 为构造的 WatermarkGenerator 处理的输入数据流类型。

TimestampAssignerSupplierWatermarkGeneratorSupplier 均继承了 Serializable,所以WatermarkStrategy 也继承了 Serializable,是可序列化的。这是因为在分布式计算过程中,WatermarkStrategy 可能会在不同节点之间传输。

接口方法

需要实现或重写的方法

实现 WatermarkStrategy 只需要实现 createWatermarkGenerator 方法,也可以根据需要重写 createTimestampAssignergetAlignmentParameters 方法。

WatermarkStrategy 接口需要实现如下 3 个方法:

  • createWatermarkGenerator:返回 WatermarkGenerator 实例,这个方法没有默认实现
  • createTimestampAssigner:返回 TimestampAssigner 实例,这个方法的默认实现返回 RecordTimestampAssigner 类的实例
  • getAlignmentParameters:返回控制 watermark 对齐的参数实例,这个方法的默认实现返回不需要对齐 watermark 的参数实例

源码flink-core/src/main/java/org/apache/flink/api/common/eventtime/WatermarkStrategy.java#L59Github

@Override
WatermarkGenerator<T> createWatermarkGenerator(WatermarkGeneratorSupplier.Context context);

@Override
default TimestampAssigner<T> createTimestampAssigner(TimestampAssignerSupplier.Context context) {
 return new RecordTimestampAssigner<>();
}

@PublicEvolving
default WatermarkAlignmentParams getAlignmentParameters() {
 return WatermarkAlignmentParams.WATERMARK_ALIGNMENT_DISABLED;
}

可以看到,除了 createWatermarkGenerator 外,createTimestampAssignergetAlignmentParametersWatermarkStrategy 接口中均有默认实现并返回默认值。

指定 WatermarkGenerator 的方法

WatermarkStrategy 接口提供了如下 4 个指定 WatermarkGenerator 的默认方法。因为 WatermarkStrategy 接口只有 createWatermarkGenerator 这 1 个方法没有默认实现,所以在实现上,就是用 lambda 表达式实现了 WatermarkStrategy 接口。

  • forMonotonousTimestamps:使用 AscendingTimestampsWatermarks 生成 watermark,适用于事件时间单调递增的场景
  • forBoundedOutOfOrderness:使用 BoundedOutOfOrdernessWatermarks 生成 watermark,适用于事件时间虽然不单调递增,但延迟时间有限的场景
  • forGenerator:使用参数提供的 WatermarkGeneratorSupplier 生成的 watermark 生成器
  • noWatermarks:不使用 watermark

源码flink-core/src/main/java/org/apache/flink/api/common/eventtime/WatermarkStrategy.java#L197Github

static <T> WatermarkStrategy<T> forMonotonousTimestamps() {
 return (ctx) -> new AscendingTimestampsWatermarks<>();
}

static <T> WatermarkStrategy<T> forBoundedOutOfOrderness(Duration maxOutOfOrderness) {
 return (ctx) -> new BoundedOutOfOrdernessWatermarks<>(maxOutOfOrderness);
}

static <T> WatermarkStrategy<T> forGenerator(WatermarkGeneratorSupplier<T> generatorSupplier) {
 return generatorSupplier::createWatermarkGenerator;
}

static <T> WatermarkStrategy<T> noWatermarks() {
 return (ctx) -> new NoWatermarksGenerator<>();
}
指定 TimestampAssigner 的方法

WatermarkStrategy 接口提供了如下 3 个指定 TimestampAssigner 的默认方法。这些方法会创建一个新的 WatermarkStrategy 类,并将调用该方法的基础 WatermarkStrategy 类封装起来;在调用新类的 createWatermarkGenerator 方法时,会使用新类中重写的方法;在调用新类的其他方法时,会返回被封装的基础类的方法。

  • withTimestampAssigner(TimestampAssignerSupplier<T> timestampAssigner):使用参数指定的 TimestampAssigner 的提供者类
  • withTimestampAssigner(SerializableTimestampAssigner<T> timestampAssigner):使用参数指定的可序列化的 TimestampAssigner
  • withIdleness(Duration idleTimeout):使用可处理空闲数据源的 WatermarkStrategyWithIdleness,其参数判定为空闲的时长

源码flink-core/src/main/java/org/apache/flink/api/common/eventtime/WatermarkStrategy.java#L92Github

default WatermarkStrategy<T> withTimestampAssigner(
     TimestampAssignerSupplier<T> timestampAssigner) {
 checkNotNull(timestampAssigner, "timestampAssigner");
 return new WatermarkStrategyWithTimestampAssigner<>(this, timestampAssigner);
}

default WatermarkStrategy<T> withTimestampAssigner(
     SerializableTimestampAssigner<T> timestampAssigner) {
 checkNotNull(timestampAssigner, "timestampAssigner");
 return new WatermarkStrategyWithTimestampAssigner<>(
         this, TimestampAssignerSupplier.of(timestampAssigner));
}

default WatermarkStrategy<T> withIdleness(Duration idleTimeout) {
 checkNotNull(idleTimeout, "idleTimeout");
 checkArgument(
         !(idleTimeout.isZero() || idleTimeout.isNegative()),
         "idleTimeout must be greater than zero");
 return new WatermarkStrategyWithIdleness<>(this, idleTimeout);
}
指定 AlignmentParameters 的方法

与指定 TimestampAssigner 的方法类似,指定 AlignmentParameters 的 2 个方法也会创建新类将基础 WatermarkStrategy 类封装起来,并重写新类的 getAlignmentParameters 方法。

  • withWatermarkAlignment(String watermarkGroup, Duration maxAllowedWatermarkDrift):指定 watermark 对齐策略,watermarkGroup 参数指定 watermark 的组名,maxAllowedWatermarkDrift 指定在暂停消费前允许超出 watermark 时间
  • withWatermarkAlignment(String watermarkGroup, Duration maxAllowedWatermarkDrift, Duration updateInterval):指定 watermark 对齐策略,updateInterval 参数指定 task 上报 watermark 以及调度器制定对齐 watermark 的时间间隔
@PublicEvolving
default WatermarkStrategy<T> withWatermarkAlignment(
        String watermarkGroup, Duration maxAllowedWatermarkDrift) {
    return withWatermarkAlignment(
            watermarkGroup,
            maxAllowedWatermarkDrift,
            WatermarksWithWatermarkAlignment.DEFAULT_UPDATE_INTERVAL);
}

@PublicEvolving
default WatermarkStrategy<T> withWatermarkAlignment(
        String watermarkGroup, Duration maxAllowedWatermarkDrift, Duration updateInterval) {
    return new WatermarksWithWatermarkAlignment<T>(
            this, watermarkGroup, maxAllowedWatermarkDrift, updateInterval);
}

整体说明

通过上述设计,使 WatermarkStrategy 接口允许使用实现 WatermarkGenerator 方法的 Java Lambda 表达式实现;对于已实现的 WatermarkStrategy 匿名类,允许通过调用指定 TimestampAssignerAlignmentParameters 的方法,来覆盖掉这两个方法的默认实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值