AWS
Spark
EMR

SparkアプリケーションのデバッグTIPS

More than 1 year has passed since last update.

Spark UIでスレッドダンプを見る

どこかで詰まってる/デッドロックしているなどを調べたい場合、スレッドダンプを見るのが有効ですが、それだけならSpark UI上でできます。

Screen Shot 2017-09-03 at 10.43.47 PM.png

Screen Shot 2017-09-03 at 10.44.12 PM.png

EMR上でJMXリモートデバッグ

ここではjvisualvmを使うことにします。

jvisualvmの準備

jvisualvmにプラグインを入れておくと捗ります。

Tools > Pluginsからプラグイン管理画面を開き、Threads Inspectorあたりは入れておくと便利です。

ステップを追加する

前提

  • アプリケーションはjarに固めてs3://path/to/app.jarに置いてあるとします
  • command-runner.jarspark-submitする方法でステップを実行します
  • EMRクラスタのmasterおよび各ノードは、22番が空いてるものとします

EMRにステップの追加

以下のようなコマンドラインオプションをつけてステップを追加します。

spark-submit --deploy-mode cluster --class com.example.Main --master yarn-cluster \
  --conf "spark.executor.extraJavaOptions=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=8002 -Dcom.sun.management.jmxremote.rmi.port=8002 -Djava.rmi.server.hostname=127.0.0.1" \
  --conf "spark.driver.extraJavaOptions=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=8003 -Dcom.sun.management.jmxremote.rmi.port=8003 -Djava.rmi.server.hostname=127.0.0.1" \
  --num-executors 3 --driver-memory 2g --executor-memory 5g --executor-cores 2 \ # このへんはお好みで
  s3://path/to/app.jar

これで、driverプロセスに対しては8003、executorプロセスに対しては8002でjmx接続できるようになります。

今回は、executorプロセスに接続してみます。

※注意

一つのノードで複数のexecutorが割り当てられうる設定で実行した場合、これだと8002がバッティングする可能性があります。

そういった場合はcom.sun.management.jmxremote.port=0として、動的にポートを取得するなどの手段をとる必要があります。

executorプロセスの実行されているノードの特定

YARNクラスタ上のどのノードでexecutorが実行されるかは動的に決まるため、各ノードにSSHで入ってlsofなどで8002番が使われているかどうか確認し、つなぐ先のノードを特定します。

ここでは、ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.comだったとします。

SSHトンネルを開く

手元のマシンで以下のコマンドを実行し、8002番のSSHトンネルを開きます。

$ ssh -i key.pem -NL 8002:ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com:8002 hadoop@ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com

jvisualvmから接続

あとは127.0.0.1:8002に対してjvisualvmから接続すればOKです。

IntelliJでステップ実行する(localモード)

IntelliJのリモートデバッグを使えば、Sparkアプリケーションをステップ実行などできます。

ここではlocalモードで行います。(EMR上でもできるはずだけど)

前提

  • sparkバイナリを落として/path/to/spark_homeに解凍しておきます
  • アプリケーションはjarに固めて/path/to/app.jarに置いておきます

IntelliJの前準備

IntelliJを起動し、Run > Edit Configurationsから、リモートデバッグ用のconfigurationを追加しておきます。

Screen Shot 2017-09-03 at 11.23.02 PM.png

+からRemoteを選択すれば勝手にこれが入力されています。

spark-submit

リモートデバッグ用のオプションをつけて、spark-submitします。

$ cd /path/to/spark_home
$ ./bin/spark-submit --master local \
    --driver-java-options "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005" \
    /path/to/app.jar

IntelliJでリモートデバッグを開始

少し経ってSparkアプリケーションが起動したら、さきほど作成したconfigurationを実行すれば、いつものようにブレークポイントを貼ったりスレッドの状態を見たりwatchを仕込んだりできます。