CLP Jinxin: 技術実践|Flink マルチスレッドで異種クラスタの動的な負荷分散を実現

はじめに: Apache Flink は、境界のないデータ ストリームと境界のあるデータ ストリームでステートフルな計算を行うためのフレームワークおよび分散処理エンジンです。この記事は主に実際のケースから始まり、著者の実践的な経験を組み合わせて、異種クラスターがアプリケーション シナリオで負荷分散を実現できない場合に、Flink のカスタム マルチスレッドを介して異種クラスターの動的な負荷分散を実現する方法を読者と共有します。

● 1. はじめに

● 2. 問題点と解決策

 ● 2.1 問題が発生しました

 ● 2.2 分析の考え方

 ● 2.3 解決策

● 3. 技術アーキテクチャ

●4. 施工効果

● 5. 結論

序文

リアルタイム コンピューティング アプリケーション シナリオでは、異種クラスターのリアルタイム呼び出し要件がよくあります。マシン構成やノード負荷などにより異種クラスターのサービスが負荷分散を達成できない場合、Flink のカスタム マルチスレッディング: 異種クラスターの動的な負荷分散。           

以下に例を示します。

テキスト コンテンツ識別、画像コンテンツ識別、画像 OCR などの機能制作要件はすべて、GPU デプロイメントに基づいて異種クラスターと対話する必要があります。GPU クラスタ マシンの構成を統一できない場合、負荷の不均衡が発生します。つまり、GPU クラスター内の一部のノードは処理が速く、一部のノードは処理が遅く、処理が遅いノードでは多数のタイムアウト例外が発生することが多く、それによってジョブ全体のバック プレッシャーが発生します。

そのフローチャートは次のとおりです。

Flink の分散固有の利点を利用して、タスク内で Thrift RPC を介してモデル サービスを呼び出し、結果をリアルタイムで取得して、それを特徴エンジニアリングに書き込み、機能を構築してリンク全体を生成します。

写真

問題と解決策

問題が発生します:

モデル サービスにデプロイされた複数のノードは互いに完全に独立しており、各ノードはオンライン/オフラインになった後、ステータスを ZooKeeper に更新します。Flink タスクの各サブタスクは、最新の利用可能なノードをすべて取得するためにウォッチを登録します。サブタスクに流入するデータごとに、データの推論を完了するためにノードを選択する必要があります。

初期段階ではランダム戦略を使用してノードを選択していましたが、使用の過程で、サーバー側のモデルノードのパフォーマンスが低くなると、データ推論に時間がかかることがわかり、最終的にはフリンクタスクにつながるバックプレッシャー。サーバーの観点から見ると、多くのモデル ノードがフル稼働ではありませんが、クライアントに反映されるサーバーのパフォーマンスは十分ではなく、処理の合計 QPS は非常に低くなります。

さらに、モデル サービスと通信するときは、同期戦略を採用しています。推論に時間がかかり、QPS が高い一部のタスクでは、データ リクエストを完了するために十分な同時実行性が必要です。ただし、これらのタスクのリソース使用率は低く、これは運用環境における大きな問題点でもあります。

写真

アイデアの分析:

上の図に基づいて、次の分析を行います。

理想的な状況では、サーバーにノード 1、ノード 2、およびノー​​ド 3 があり、3 つのノードのパフォーマンスが同じで、各ノードが 32 個の並列処理を行うと仮定します。各データの処理時間を800msとすると、各ノードの処理能力は40個/秒、3ノードフル負荷時の処理能力は120個/秒となります。

実際の本番環境では、サーバー上に展開されるマシンの各ノードの処理能力が異なります。その違いには主に 3 つの理由があります。

 GPU 物理マシンにはさまざまな仕様があり、パフォーマンスも大きく異なるため、展開中にノードが同じバッチのマシンに展開されるようにすることは困難です。

 1 台のマシン上で複数のモデル サービスを混在させると、相互に影響を及ぼします。

 一部のノードが配置されているマシンのネットワークおよびディスクの障害も、差異の原因となります。

たとえば、ノード 1 と 2 は高性能マシンにデプロイされており、ノードの並列処理は 32 で、1 つのデータの処理時間は 800 ミリ秒です。ノード 3 は低パフォーマンスのマシンにデプロイされており、ノードの並列処理は 32 で、1 回のデータ処理に 2400 ミリ秒かかるため、ノード 3 の処理能力は 13.3 レコード/秒と見なされます。ノードをランダムに選択する戦略も採用されており、1 秒間に合計 40 個のデータが送信されると、ノード 3 はすでにパフォーマンスのボトルネックに達しています。この時点でノード 3 で処理するデータがさらに選択されていると仮定すると、そのデータはサーバー側のキューにのみキューイングされ、キューがいっぱいの場合は接続が拒否されます。

タスクが実行されると、ノード 3 の待ちキューのデータが増加し、それに応じてクライアントがリクエストを送信してから結果を返すまでにかかる時間も増加します。このとき、サブタスクがこのノードを選択すると、サブタスクはこのリクエストを完了するまでに長時間待機する必要があります。このプロセス中に上流のデータが流入し続けると、サブタスクの入力チャネルが徐々に枯渇し、パブリック バッファー プールのスペースがいっぱいになり、サブタスク 2 がスタックしてしまいます。また、上流のオペレーターが Rebalance を使用するため、Flink タスク全体が最終的にスタックします。

写真

これは典型的なバレル効果であり、実際のアプリケーション シナリオでは、単一ノードのパフォーマンスが低下したり障害が発生したりすると、タスク全体の安定性に影響を及ぼします。

解決:

事故の原因を分析した後、各ノードに重みを設定することを提案します。モデル ノードは定期的に重み値を ZooKeeper に報告し、クライアントは重みを通じて対応するトラフィックを各ノードに割り当てます。このアイデアは非常に優れており、実際に一定の結果を達成していますが、小さな問題があります。そうすると、各ノードのトラフィックが常にジッターすることになり、ジッターの頻度はレポートの時間と正の相関があります。監視の観点からすると、処理されるデータの総量も不安定になります。

写真

写真

この問題が最初に軽減された後、私たちはこの問題を解決する他のより良い方法があるかどうかを検討し始めました。モデル ノードが遅い場合、サブタスクがスタックすることが知られていますが、このサブタスクは本質的にスロット、つまりスレッドであるため、この問題を解決するためにマルチスレッドを使用できるでしょうか? これを念頭に置いて、私たちは他の 2 つのソリューション、非同期 I/O とマルチスレッドを試しました。

■ 非同期 I/O ソリューション

Flink はバージョン 1.2 で Async I/O を導入しました。その主な目的は、外部システムと対話するときにネットワーク遅延がシステムのボトルネックになるという問題を解決することです。公開された API を通じて、操作の最大数を設定できます。これは、単純にスロット内の同時非同期リクエストの最大数として理解されます。テスト中は 3 つのノードを準備し、1 つのノードの処理に 2000 ミリ秒かかり、他の 2 つのノードの処理に 500 ミリ秒かかりました。

タスクは起動後数分以内に正常に実行されますが、その後、処理速度の遅いノードのサーバーキュー蓄積長がどんどん大きくなり、最終的には150程度で安定します。同時にタイムアウト失敗率も増加し始めます。高い。この方法では、高速ノードと低速ノードによって引き起こされるバック プレッシャーのスタックとリソース使用率の問題は解決できますが、トラフィック分散の問題はまだ解決できないことがわかります。

写真

写真

■ マルチスレッド ソリューション

各スロット内に生産者消費者モデルを実装し、モデル ノードと同じ数のスレッドを作成し、各スレッドが固定ノードを要求するようにします。このノードがスタックしたり、処理速度が遅くなったりしても、影響を受けるだけです。現在のスレッドがサブタスク全体に及ぼす影響は限定的です。

写真

上の図に示すように、スロットには複数のスレッドが含まれており、個々のスレッドに対応するサービス ノードの問題は、他のスレッドの消費には影響しません。このようにして、適応的なトラフィック分散戦略が実現され、各スレッドはサーバー Pod に対応し、このスレッド適応型ブロック方式により、遅いノードによる消費量を減らし、速いノードによる消費量を増やすという目的を達成できます。

Flink がスロットを最小リソース粒度として取り、それを調整する場合、スロットから複数のスレッドを開始することで同時実行性が向上し、それによってスロット全体の数が減り、リソースを削減しながらリソース使用率が向上します。

テクノロジーアーキテクチャ

Flink タスクでは、RPC 通信の負荷分散の問題を解決するためにマルチスレッド ソリューションが使用されています。それに応じてプログラミング モデルを変更する必要があります。具体的な変更は次のとおりです。

写真

写真

施工効果

前後のデータを比較すると、マルチスレッド ソリューションを採用した後でも、その効果が依然として明らかであることがわかりました。下図のサーバー側の処理時間指標から、125.172で終わるノードの処理時間は約1.7秒であることがわかります。また、トラフィック分配量指標では、ノードに割り当てられているトラフィックが多いことがわかります。約 5 個/秒です。160.25 ノードの処理時間は約 0.14 秒、割り当てられたトラフィックは約 58/秒で、これは概ね予想どおりです。

写真

写真

同時に、サービス全体の安定性を確保するために、キャッシュ キューの長さ、モデルの失敗率、リンク時間の消費量、書き込み機能の失敗率などの監視指標を追加しました。

写真

エピローグ

この記事では主に、異種クラスターで Flink が呼び出される場合、サーバーがトラフィックを分散できない場合、クライアントはマルチスレッドを通じてトラフィックの動的な負荷分散を実装でき、サーバーが高構成モデルと低構成モデルとの互換性を確保できることを紹介します。機械の稼働効率を向上させます。ただし、この記事で使用されているマルチスレッド オペレーターはステートレス (ステートレス) であり、ステートフル オペレーターについては適切に検討する必要があることに注意する必要があります。さらに、サーバーが自律的にノードを割り当てることができるコンポーネントである場合は、非同期 I/O ソリューションの使用を選択できます。

おすすめ

転載: blog.csdn.net/zhongdianjinxin/article/details/132278317