Apache Spark UI を使用したデバッグ

この記事では、 Apache Spark アプリケーションの内部を確認するために使用できるさまざまなデバッグ オプションについて説明します。 確認すべき 3 つの重要な場所は次のとおりです。

  • Spark UI

  • ドライバーログ

  • エグゼキューターのログ

Spark UI を使用してコストとパフォーマンスの問題を診断する手順については、「Spark UI を使用してコストとパフォーマンスの問題を診断する」を参照してください。

Spark UI

ジョブを開始すると、Spark UI にアプリケーションで何が起こっているかに関する情報が表示されます。 Spark UI にアクセスするには、添付のコンピュートをクリックします。

ストリーミングタブ

Spark UI にアクセスすると、このコンピュートでストリーミング ジョブが実行されている場合は、[ストリーミング] タブが表示されます。 このコンピュートでストリーミング ジョブが実行されていない場合、このタブは表示されません。 ドライバー ログにスキップして、ストリーミング ジョブの開始中に発生した可能性のある例外を確認する方法を学習できます。

このページで最初に探すことは、ストリーミング アプリケーションがソースから入力イベントを受信しているかどうかを確認することです。 この場合、ジョブが 1 秒あたり 1000 イベントを受信していることがわかります。

複数の入力ストリームを受信するアプリケーションがある場合は、 「入力レート」リンクをクリックすると、各レシーバーで受信したイベントの数が表示されます。

処理時間

下にスクロールすると、[ 処理時間] のグラフが表示されます。 これは、ストリーミング ジョブのパフォーマンスを理解するための重要なグラフの 1 つです。 一般的な経験則として、各バッチをバッチ処理時間の 80% 以内に処理できれば良好です。

このアプリケーションのバッチ間隔は 2 秒でした。 平均処理時間は 450 ミリ秒で、バッチ間隔を十分に下回っています。 平均処理時間がバッチ間隔に近いかそれより長い場合、ストリーミング アプリケーションがキューに登録され、すぐにバックログが発生し、最終的にはストリーミング ジョブが停止する可能性があります。

完了したバッチ

ページの最後に、完了したすべてのバッチのリストが表示されます。 このページには、完了した最後の 1000 バッチに関する詳細が表示されます。 テーブルから、各バッチで処理されたイベントの数とその処理時間を取得できます。 バッチの 1 つで何が起こったかを詳しく知りたい場合は、バッチのリンクをクリックしてバッチの詳細ページにアクセスできます。

バッチ詳細ページ

このページには、バッチについて知りたいすべての詳細が記載されています。 次の 2 つの重要な点があります。

  • 入力: バッチへの入力に関する詳細が含まれます。 この場合、このバッチの Spark 構造化ストリーミングによって読み取られた Apache Kafka トピック、パーティション、およびオフセットに関する詳細が含まれています。 TextFileStream の場合、このバッチで読み取られたファイル名のリストが表示されます。 これは、テキスト ファイルから読み取るストリーミング アプリケーションのデバッグを開始する最良の方法です。

  • 処理: ジョブ ID へのリンクをクリックすると、このバッチ中に実行された処理に関する詳細がすべて表示されます。

ジョブの詳細ページ

ジョブの詳細ページには、DAG の視覚化が表示されます。 これは、各バッチの操作の順序と依存関係を理解するのに非常に役立ちます。 この場合、Kafka ダイレクト ストリームからのバッチ読み取り入力に続いて、フラット マップ操作、次にマップ操作が行われていることがわかります。 次に、結果のストリームを使用して、updateStateByKey を使用してグローバル状態を更新しました。 (灰色のボックスは、スキップされたステージを表します。 Spark は、再計算する必要がない場合、いくつかのステージをスキップできるほど賢いです。 データがチェックポイントまたはキャッシュされている場合、Spark はそれらのステージの再計算をスキップします。 この場合、これらのステージは、 updateStateBykeyによる前のバッチへの依存関係に対応します。 Spark 構造化ストリーミングはストリームを内部的にチェックポイントし、以前のバッチに依存するのではなくチェックポイントから読み取るため、灰色のステージとして表示されます。)

ページの下部には、このバッチに対して実行されたジョブのリストも表示されます。 説明内のリンクをクリックすると、タスク レベルの実行をさらに詳しく調べることができます。

タスクの詳細ページ

これは、Spark アプリケーションの Spark UI から実行できる最も詳細なデバッグ レベルです。 このページには、このバッチに対して実行されたすべてのタスクが含まれています。 ストリーミング アプリケーションのパフォーマンスの問題を調査している場合、このページには、実行されたタスクの数、タスクが実行された場所 (どのエグゼキューター)、シャッフル情報などの情報が表示されます。

ヒント

処理中に十分な並列性が得られるように、コンピュート内の複数のエグゼキューター (ノード) でタスクが実行されていることを確認してください。 レシーバーが 1 つだけの場合、コンピュートに複数のエグゼキュータがあるにもかかわらず、1 つのエグゼキュータだけがすべての作業を行うことがあります。

スレッド・ダンプ

スレッド ダンプには、JVM のスレッド状態のスナップショットが表示されます。

スレッド ダンプは、特定のハングしたタスクや実行速度が遅いタスクをデバッグするのに役立ちます。 Spark UI で特定のタスクのスレッド ダンプを表示するには:

  1. 「ジョブ」タブをクリックします。

  2. 「ジョブ」テーブルで、表示したいスレッド・ダンプに対応するターゲット・ジョブを見つけ、 「説明」列のリンクをクリックします。

  3. ジョブの「ステージ」テーブルで、表示するスレッド ダンプに対応するターゲット ステージを見つけて、 「説明」列のリンクをクリックします。

  4. ステージのタスクリストで、表示するスレッド ダンプに対応するターゲット タスクを見つけ、そのタスク IDエグゼキューター IDの値をメモします。

  5. 「エグゼキューター」タブをクリックします。

  6. エグゼキューターテーブルで、前にメモしたエグゼキューター ID値に対応するエグゼキューター ID値を含む行を見つけます。 その行で、[ スレッド ダンプ ] 列のリンクをクリックします。

  7. エグゼキューターのスレッド ダンプテーブルで、スレッド名列にTIDと、前にメモしたタスク ID値が含まれている行をクリックします。 (タスクの実行が終了した場合、一致するスレッドは見つかりません)。 タスクのスレッド ダンプが表示されます。

スレッド ダンプは、ドライバーがハングしているように見える (たとえば、Spark の進行状況バーが表示されていない) 場合やクエリが進行していない (たとえば、Spark の進行状況バーが 100% で止まっている) 問題のデバッグにも役立ちます。 Spark UI でドライバーのスレッド ダンプを表示するには:

  1. 「エグゼキューター」タブをクリックします。

  2. エグゼキューターテーブルのドライバー行で、 [スレッド ダンプ]列のリンクをクリックします。 ドライバーのスレッド ダンプが表示されます。

ドライバー ログ

ドライバー ログは、次の 2 つの目的で役立ちます。

  • 例外: Spark UI に [ストリーミング] タブが表示されない場合があります。 これは、何らかの例外によりストリーミング ジョブが開始されなかったためです。 ドライバー ログをドリルダウンして、例外のスタック トレースを確認できます。 場合によっては、ストリーミング ジョブが適切に開始されている可能性があります。 ただし、すべてのバッチが [完了したバッチ] セクションに表示されないことがわかります。 これらはすべて処理中または失敗状態である可能性があります。 このような場合も、ドライバー ログは、根本的な問題の性質を理解するのに便利です。

  • 印刷: DAG の一部としての印刷ステートメントもログに表示されます。

エグゼキューターのログ

エグゼキューターのログは、特定のタスクが不正に動作していることがわかり、特定のタスクのログを確認したい場合に役立つことがあります。 上記のタスク詳細ページから、タスクが実行されたエグゼキューターを取得できます。 それを取得したら、コンピュート UI ページに移動し、# ノードをクリックしてからマスターをクリックします。 マスター ページにはすべてのワーカーがリストされます。 疑わしいタスクが実行されたワーカーを選択すると、log4j 出力が表示されます。