Apache Flinkバッチランナーへのウィンドウ化機能の追加

Apache Flinkバッチランナーにウィンドウのサポートを追加するという大きなマイルストーンを最近達成しました。この記事では、この変更がApache Beamユーザーにとって何を意味するのか、そして実装の詳細の一部を説明します。

まず、Beamプログラムの実行と、それが本日の記事にどのように関連しているかについて簡単に説明します。Beamパイプラインには、有限ソースと無限ソースを含めることができます。パイプラインに有限ソースのみが含まれている場合、バッチ方式で実行できます。無限ソースが含まれている場合は、ストリーミング方式で実行する必要があります。BeamパイプラインをFlinkで実行する場合、実行モードを選択する必要はありません。内部的には、Flinkランナーは、パイプラインに無限ソースが使用されているかどうかに応じて、パイプラインをFlink DataSetプログラムまたはDataStreamプログラムに変換します。以下では、「バッチランナー」とは、Flinkランナーがバッチ実行モードであることを意味します。

これはユーザーにとって何を意味するのでしょうか?

ウィンドウのサポートは、FlinkバッチランナーをBeamモデルと互換性を持たせるための最後のピースでした。バッチランナーの最新の変更により、ユーザーは有限ソースのみを含むパイプラインを実行できるようになり、結果はGoogle Dataflow SDKから提供された初期コードに含まれる元の参照実装ランナーの結果と一致することが保証されます。

変更の最も明白な部分は、要素にウィンドウを割り当てることができるようになり、ランナーがGroupByKeyおよびCombine操作でこれらのウィンドウを尊重するようになったことです。それほど明白ではない変更は、サイド入力に関するものです。Beamモデルでは、サイド入力はウィンドウを考慮します。メイン入力の値が処理されている場合、処理関数であるDoFnは、正しいウィンドウに対応するサイド入力のみを使用できます。

サイド入力のセマンティクスを正しくすることは、それ自体が重要なマイルストーンです。ランナー実装の正確性を検証するための大規模な単体テストスイートを使用できるようになるためです。これらのテストは、Beamプログラミングモデルのあらゆる詳細を検証し、ランナーによって生成された結果が正しい実装から期待される結果と一致することを検証します。スイートでは、サイド入力を使用して、期待される結果と実際の実績を比較します。これらのテストを定期的に実行することで、実装がユーザー指定のパイプラインに対して正しい結果を生成することをより確信できます。

内部構造

変更の基礎は、生成されたFlink変換にWindowedValueが導入されたことです。以前は、Beam PCollection<T>DataSet<T>に変換されていました。現在、代わりにDataSet<WindowedValue<T>>を作成します。 WindowedValue<T>は、タイムスタンプや割り当てられたウィンドウなど、値に関するメタデータを格納します。

この基本的な変更が終わったので、サイド入力でウィンドウが考慮され、CombineGroupByKeyがウィンドウを正しく処理することを確認するだけで済みます。そこで難しいのは、セッションウィンドウなどのマージウィンドウの処理です。これらについては、基本的にマージするWindowFnの動作を独自のコードでエミュレートします。

サイド入力が機能するようになった後、前述のテストスイートを有効にして、ランナーがBeamモデルに対してどのように動作するかを確認できました。予想通り、かなりの食い違いがありましたが、すべて解決することができました。その過程で、ランナーの実装もスリム化しました。たとえば、ソースとシンクのカスタム変換をすべて削除し、現在はこれらのためにBeamコードのみに依存しているため、メンテナンスのオーバーヘッドが大幅に削減されています。

まとめ

Flinkバッチランナーにウィンドウのサポートを追加するという大きなマイルストーンを達成し、Beamモデルとの互換性を実現しました。ランナーで実行できるようになった大規模なテストスイートにより、実装の正確性と、将来もその状態が維持されることについて確信しています。