如何在 Apache Flink Batch Runner 中添加窗口

我们最近取得了重大里程碑,为 Apache Flink Batch runner 添加了对窗口的支持。在这篇文章中,我们想解释这对 Apache Beam 用户意味着什么,并重点介绍一些实现细节。

不过,在我们开始之前,让我们快速谈谈 Beam 程序的执行以及这与今天的文章有何关系。Beam 管道可以包含有界和无界源。如果管道只包含有界源,则可以以批处理方式执行,如果它包含一些无界源,则必须以流式方式执行。在 Flink 上执行 Beam 管道时,您不必选择执行模式。在内部,Flink 运行器将管道转换为 Flink DataSet 程序或 DataStream 程序,具体取决于管道中是否使用了无界源。在以下内容中,当我们说“Batch runner”时,我们实际上指的是 Flink 运行器处于批处理执行模式。

这对用户意味着什么?

对窗口的支持是使 Flink Batch runner 与 Beam 模型兼容的最后一个缺失拼图。通过对 Batch runner 的最新更改,用户现在可以运行任何仅包含有界源的管道,并确信结果与 Google 在来自 Google Dataflow SDK 的初始代码发布中提供的原始参考实现运行器一致。

更改中最明显的部分是,现在可以将窗口分配给元素,并且运行器会为 GroupByKeyCombine 操作尊重这些窗口。一个不太明显的更改涉及边输入。在 Beam 模型中,边输入会尊重窗口;当处理主输入的值时,只有对应于正确窗口的边输入可用于处理函数 DoFn

正确获取边输入语义本身就是一个重要的里程碑,因为它允许使用一组大型单元测试来验证运行器实现的正确性。这些测试会测试 Beam 编程模型的每一个细微之处,并验证运行器产生的结果与您对正确实现的预期一致。在套件中,边输入用于将预期结果与实际结果进行比较。通过定期执行这些测试,我们现在可以更加确信该实现会为用户指定的管道产生正确的结果。

幕后

更改的基础是在生成的 Flink 变换中引入了 WindowedValue。以前,Beam PCollection<T> 将被转换为 DataSet<T>。现在,我们改为创建 DataSet<WindowedValue<T>>WindowedValue<T> 存储有关该值的元数据,例如时间戳和分配给它的窗口。

有了这个基本更改,我们只需要确保边输入尊重窗口,并且 CombineGroupByKey 正确处理窗口。这里棘手的部分是处理合并窗口,例如会话窗口。对于这些窗口,我们实际上在我们自己的代码中模拟了合并 WindowFn 的行为。

在边输入正常工作后,我们可以启用前面提到的测试套件来检查运行器在 Beam 模型方面的表现如何。正如预期的那样,存在一些差异,但我们设法解决了所有差异。在此过程中,我们还精简了运行器实现。例如,我们删除了对源和接收器的所有自定义翻译,现在仅依赖 Beam 代码来完成这些操作,从而极大地减少了维护开销。

总结

我们在为 Flink Batch runner 添加窗口支持方面取得了重大里程碑,使其与 Beam 模型兼容。由于现在可以在运行器上执行的大型测试套件,我们也对实现的正确性以及将来保持这种状态充满信心。