建築
すべての分散コンピューティング エンジンにはクラスター リソース マネージャーが必要です。たとえば、MapReduce および Spark プログラムは YARN クラスターまたは Mesos で実行できます。Flink も分散コンピューティング エンジンであり、Flink プログラムを実行するにはリソース マネージャーも必要です。各分散コンピューティング エンジンを学ぶために、最初に理解する必要があるのは、開発した分散アプリケーションがクラスター内でどのように実行されるかということです。これには、間違いなくリソース マネージャーとの対話が含まれます。実際、リソース管理はクラスターの抽象化とみなすことができます。
Flink クラスターが関与する重要な役割を見てみましょう。
- クライアント
クライアントは、記述されたコードをプログラムのデータフローに変換し、データフローを最適化し、データフロー グラフを生成して、ジョブをジョブマネージャーに送信します。私たちが書く Flink コードは主に、Flink プログラムがクラスター内でどのように実行されるべきかを記述するために使用されます。もちろん、Flink クラスターは、書かれたスタンドアロン プログラムを実行するように逐次的に実行されるわけではありません。ジョブを 1 つずつ受け入れるだけで、ジョブ内のタスクを 1 つずつ実行します。
- ジョブマネージャー
ジョブ マネージャーは実際には Flink クラスターのジョブ マネージャーであり、クラスターのコンピューティング リソースのスケジュールと管理を担当します。
- タスクマネージャー
クラスターは多くの場合、特定のタスクの管理と実行を担当する多数のタスク マネージャーで構成されます。タスク マネージャーとタスク マネージャーは相互に通信することもできます。
コンポーネント |
使用 |
成し遂げる |
フリンククライアント |
バッチ アプリケーションまたはストリーミング アプリケーションをデータフロー グラフにコンパイルし、ジョブマネージャーに送信します。 |
|
ジョブマネージャー |
Flinkシステムの管理ノードはすべてのタスクマネージャーを管理し、どのタスクマネージャーがユーザータスクを実行するかを決定します。 JobManager には 3 つのジョブ送信モードがあります アプリケーションモード ジョブごとのモード セッションモード |
|
タスクマネージャー |
Flinkシステムのビジネス実行ノードは、特定のユーザー タスクとFlink ジョブを実行します。 |
スケジュール設定
Flink はタスク スロットを通じて実行リソースを定義します。各タスク マネージャーには 1 つ以上のタスク スロットがあり、各タスク スロットは複数の並列タスクで構成されるパイプラインを実行できます。このようなパイプラインは、複数の連続したタスクで構成されます。
各スロットが使用できるリソースは固定されており、たとえば、タスク マネージャーに 3 つのスロットが構成されている場合、各スロットが使用できるメモリはタスク マネージャーが管理するメモリの 1/3 になります。スロット間でメモリ リソースの競合はありません。Flink ではタスクマネージャーのスロット数を調整することができ、スロット数が 1 の場合は各タスクが独立した JVM で実行されることを意味します。これが 1 より大きい場合は、1 つの JVM で複数のタスクが実行されていることを意味します。
スロット実行ごとに 1 つのタスクを実行できます。JOB に多くの Operator と並列処理がある場合、多くのタスクが含まれることになります。Flink クラスターのデフォルト構成では、タスクはスロットを共有できます。つまり、複数のタスクを 1 つのスロットで実行できます。
クライアントは Flink コードを JobGraph に解析し、いくつかのサブタスクをタスクにパッケージ化し、各タスクはスレッドで実行されます。各タスクはタスクマネージャーのスロットで実行されます。ストリーム処理の場合、Flink は完全なパイプラインをスロットに配置します。
このようなプログラムは、それぞれ 3 つのスロットを持つ 2 つのタスクマネージャーを備えた Flink クラスターで実行されます。Flink は、各 Operator 実行インスタンスに基づいてスケジュールを設定しませんが、完全なパイプラインをスロットにスケジュールすることを優先します。ここでの並列処理設定では、完全なパイプラインがスケジュールされているスロットが 3 つあることがわかります。
これにより、プログラム動作のスループットを向上させることができる。各オペレータの並列処理を独立したスレッドで実行する場合、スレッド数が多い場合にはスレッドの切り替えとキャッシュを継続的に行う必要があり、一定のオーバーヘッドが発生します。
ジョブマネージャーのデータ構造
ジョブの実行中、ジョブマネージャーは各タスクを追跡し、次のタスクまたはタスクのグループをいつスケジュールするかを決定し、完了したタスクまたは実行の失敗を処理します。
JobManager は、演算子 (JobVertex) と中間結果 (IntermediateDataSet) を含むデータ フローの表現である JobGraph を受け取ります。各オペレーターには、並列度や実行するコードなどのプロパティがあります。
作成したコードは JobGraph に変換されます。実際、これは有向非巡回グラフでもあります。グラフ構造なのでVertex(頂点)とEdge(辺)が存在するはずです。Flink の JobGraph 頂点は JobVertex であり、これは実際には Flink の Operator であり、JobGraph のエッジは IntermediateDataSet (Operator によって処理された中間結果) です。
各 JobVertex には独自のプロパティがあります。例: 並列度、オペレーターによって実行されるコード。さらに、各 JobVertex のコードが JVM で正しく実行できるようにするために、各 JobGraph にはライブラリのセット (jar パッケージの束) も含まれている必要があります。
実際にクラスター内で Flink プログラムを実行するには、JobGraph を ExecutionGraph に変換する必要があります。実際、ExecutionGraph は、JobGraph の並列バージョン、または JobGraph の並列拡張として理解できます。
ExecutionGraph の頂点は ExecutionVertex です。JobVertex の並列処理が 50 の場合、ExecutionGraph には 50 個の ExecutionVertex (頂点) が存在します。各 ExecutionVertex には、各タスクの実行ステータスが含まれます。ExecutionGraph のエッジは IntermediatePartition です。各並列頂点に対応する中間結果データは実際にはパーティションであるためです。
仕事の状況
各 ExecutionGraph にはジョブ ステータス情報が関連付けられており、現在のジョブ実行ステータスを記述するために使用されます。
- 完全な処刑
Flink ジョブは、最初は作成された状態にあり、操作のスケジュールを開始すると実行状態に切り替わります。ジョブの実行が終了すると、終了状態に切り替わります。
- ジョブの実行に失敗しました
この期間中に障害が発生した場合、ジョブはまず失敗状態に切り替わり、実行中のタスクがすべてキャンセルされます。すべてのジョブ ノードが最終状態に達し、ジョブを再開できない場合、ジョブは失敗状態になります。
- ジョブの再開
ジョブの実行中に障害が発生し、ジョブを再開できる場合、ジョブは再開状態になり、ジョブが完全に再開されると作成済み状態になります。
- ユーザーがジョブを手動でキャンセルする
ユーザーがジョブを手動でキャンセルすると、キャンセル状態になり、実行中のすべてのタスクがキャンセルされます。実行中のすべてのタスクが最終状態になると、ジョブはキャンセル状態に移行します。
- 保留中の仕事
完了、キャンセル、失敗すると、グローバルな最終状態が発生し、ジョブのクリーンアップがトリガーされます。これらの状態とは異なり、一時停止状態は部分的な終了にすぎません。ローカル終了は、ジョブの実行が対応するジョブマネージャーによって終了されたが、クラスター内の他のジョブマネージャーは引き続き高可用性ストレージからジョブ情報を取得して再起動できることを意味します。したがって、一時停止状態のジョブは完全にはクリーンアップされません。
終了、キャンセル、および失敗の状態は、ジョブのクリーンアップをトリガーするグローバルな終了状態です。サスペンド状態はローカルの終了状態です。これは、ジョブが 1 つのジョブマネージャーで終了しても、それが HA クラスターであれば、別のジョブマネージャーが HA ストレージからジョブを取得して再起動できることを意味します。したがって、一時停止状態ではジョブは完全にはクリーンアップされません。
- タスクのステータス
ExecutionGraph 全体の実行中、各並列タスクは、作成された状態から終了または失敗するまでの複数の段階を経ます。以下の図は、さまざまな状態とそれらの間の遷移関係を示しています。タスクは複数回実行される可能性があるため (例外回復中など)、ExecutionVertex の実行は Execution によって追跡され、各 ExecutionVertex は現在の実行と前回の実行を記録します。