Upload
x1-ichi
View
1.846
Download
4
Embed Size (px)
Citation preview
自己紹介>
井上 ゆり
株式会社サイバーエージェント
アドテク本部 AMoAd所属
twitter: @iyunoriue
GitHub: x1-
HP: バツイチとインケンのエンジニアブログ http://x1.inkenkun.com/
Spark環境と用途• Sparkクラスタ : N十台, オンプレ
• Sparkクラスタ化: zookeeper + Mesos
• SparkノードのFS: HDFS-HA + GCS + S3
• GUI : Apache Zeppelin, iPython
• 開発言語 : scala
• ジョブのビルド : sbt
• 用途 : 定常ジョブ(cron実行)
アドホック分析
case.1 Spark1.5系&HDFS-HAでエラー
Sparkクラスタを1.4.0から1.5.1へバージョンアップしたところ、ジョブがfailするようになりました。
NameNodeが解決できていないようなエラーメッセージです。 ※nameservice1はHDFS-HAクラスタに設定した論理サービス名です。
内容
15/10/21 15:22:12 WARN scheduler.TaskSetManager: Lost task 0.0 in stage 0.0 (TID 0, spark003.example.com):
java.lang.IllegalArgumentException: java.net.UnknownHostException: nameservice1
at org.apache.hadoop.security.SecurityUtil.buildTokenService(SecurityUtil.java:374)
at org.apache.hadoop.hdfs.NameNodeProxies.createNonHAProxy(NameNodeProxies.java:312)
at org.apache.hadoop.hdfs.NameNodeProxies.createProxy(NameNodeProxies.java:178)
at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:665)
at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:601)
:
case.1 Spark1.5系&HDFS-HAでエラー
• HDFSのHighAvailabilityを無効にすると正常に終了します。
• また、クラスタのバージョンを1.4系に戻すと正常に終了します。
• JIRAにバグ報告するものの、HDFSの設定ファイルを見なおせとのこと。
SPARK-11227: Spark1.5+ HDFS HA mode throw java.net.UnknownHostException: nameservice1
https://issues.apache.org/jira/browse/SPARK-11227
Try
case.1 Spark1.5系&HDFS-HAでエラー
• Apache Zeppelinで同じ内容を実行すると正常終了するので差異を調べました。
• Zeppelinで使われているSQLContextはHiveContext。
• 私たちが使っていたSQLContextはデフォルトのSQLContext。
どうやらHiveContextが鍵のようです。
原因
case.1 Spark1.5系&HDFS-HAでエラー
• SQLContextではなくHiveContextを使うと、NameNodeの名前解決ができました。
• デフォルトのSQLContextの使用をやめて、HiveContextを使うようにしました。
解決
implicit val sqlContext = new HiveContext( sc )
case.2 executorからの応答がなくなる
Sparkでジョブを実行すると、タスクはdriverによって複数個に分割されてexecutorで実行されます。
内容
分割タスクが完了するとexecutorはdriverにレスポンスを返します。
driver
executor
executor
executor
driverタスク 結果
case.2 executorからの応答がなくなる
ところが、GCなどのためにいつまで待ってもレスポンスを返さないexecutorがたまにいます。
内容
driverは全てのexecutorのレスポンスを待ち受けるので(failしない限り)、半永久的にジョブが完了しません。
driver
executor
executor
executor
driverタスク 結果
a a
case.2 executorからの応答がなくなる
• 完了しないジョブがSparkクラスタ内のメモリ資源を確保し続けてしまいました。
• 別のジョブが開始されると、クラスタ内のメモリ解放を待ち続けるという負の待ち行列が発生してしまいました。
問題
ジョブAが確保したメモリ 空きメモリ
ジョブBが必要なメモリ
クラスタの総メモリ
不足!メモリに空きができるまで待つ
ジョブCが必要なメモリ
case.2 executorからの応答がなくなる
•spark.network.timeout: 120s
spark.network.timeoutに設定した値は、ほとんど全ての通信系タイムアウト(下記)のデフォルト値になります。
* spark.core.connection.ack.wait.timeout
* spark.akka.timeout
* spark.storage.blockManagerSlaveTimeoutMs
* spark.shuffle.io.connectionTimeout
* spark.rpc.askTimeout
* spark.rpc.lookupTimeout
Try
まずはタイムアウト関連の設定を見直しました。
case.2 executorからの応答がなくなる
•spark.dynamicAllocation.executorIdleTimeout: 60s
ダイナミック・アロケーションが有効な場合のexecutorのアイドル時間です。 ※ダイナミック・アロケーションを有効にしていないので関係ありませんでした。
Try
タイムアウトの設定ではなさそうです。
その他のタイムアウト設定。
case.2 executorからの応答がなくなる
遅延タスクを再起動するspark.speculationを設定しました。
spark.speculationがtrueに設定されていると、遅いタスクの再起動を実施します。
※DatabicksのMatei Zahariaがここ↓で回答しているように、stragglersをkillするような仕組みはないようです。 http://apache-spark-user-list.1001560.n3.nabble.com/Does-Spark-always-wait-for-stragglers-to-finish-running-td14298.html
解決.1
spark.speculation true spark.speculation.multiplier 1.5 spark.speculation.quantile 0
case.2 executorからの応答がなくなる
更に、OSのtimeoutコマンドで終了しないジョブを強制タイムアウトさせました。
タスクの強制再起動で予想外に時間がかかってしまったジョブは、強制終了させます。
解決.2
timeout 600 $SPARK_HOME/bin/spark-submit job.jar
case. ジョブのsbtテストがfailする
各テスト内でSparkコンテキストを生成してテストを実施していました。
内容
sc = new SparkContext( conf ) val rdd = sc.parallelize( Seq( 1, 2 ) ).map( id => Row( id, 0d, "", "http://example.com/" ) ) val df = sqlContext.createDataFrame( rdd, schema )
case. ジョブのsbtテストがfailする
• sbt>=0.10.0からタスクの並列実行機能が入ったため。
• SparkContextは1つのJVMプロセスで複数生成できない。
SPARK-2243: Support multiple SparkContexts in the same JVM https://issues.apache.org/jira/browse/SPARK-2243
原因
case. ジョブのsbtテストがfailする
• テスト実行時のタスク並列実行をやめました。
• build.sbtに下記を追加したところ、正常に実行されるように・・・!
解決
parallelExecution in Test := false