web-dev-qa-db-ja.com

糸でジョブをストリーミングするspark)を開始/停止する正しい方法は何ですか?

私は何時間も実験とグーグルをしてきましたが、運がありませんでした。

ローカルsparkクラスターで正常に実行されるsparkストリーミングアプリがあります。これをcloudera5.4.4にデプロイする必要があります。開始するには、バックグラウンドで継続的に実行し、停止できるようにします。

私はこれを試しました:

$ spark-submit --master yarn-cluster --class MyMain my.jar myArgs

しかし、それはこれらの行を際限なく印刷するだけです。

15/07/28 17:58:18 INFO Client: Application report for application_1438092860895_0012 (state: RUNNING)
15/07/28 17:58:19 INFO Client: Application report for application_1438092860895_0012 (state: RUNNING)

質問番号1:ストリーミングアプリなので、継続的に実行する必要があります。では、どうすれば「バックグラウンド」モードで実行できますか?ヤーンでsparkジョブを送信するために私が見つけることができるすべての例は、アプリケーションが何らかの作業を行って終了することを前提としているようです。したがって、フォアグラウンドで実行する必要があります。しかし、それはストリーミングには当てはまりません。

次は...この時点では、アプリは機能していないようです。私はそれが私の側のバグまたは設定ミスである可能性があると考えたので、ログを調べて何が起こっているのかを確認しようとしました:

$ yarn logs -applicationId application_1438092860895_012

しかし、それは私に教えてくれます:

/tmp/logs/hdfs/logs/application_1438092860895_0012does not have any log files.

だから質問番号2:アプリケーションが実行中の場合、なぜログファイルがないのですか?

だから結局私はそれを殺さなければならなかった:

$ yarn application -kill application_1438092860895_012

それは質問番号をもたらします:私が最終的にアプリを起動してバックグラウンドで実行できると仮定すると、「yarn application-kill」はそれを停止するための好ましい方法ですか?

11
Kevin Pauli
  1. spark-submitコンソールを閉じることができます。書き込み[〜#〜]実行中[〜#〜]状態のとき、ジョブはすでにバックグラウンドで実行されています。
  2. アプリケーションが完了したの直後にログが表示されます。実行時に、すべてのログはローカルのワーカーノードで直接アクセスでき(YARNリソースマネージャーのWeb UIで確認できます)、HDFSに集約されますジョブの終了後
  3. yarn application -killはおそらくストリーミングアプリケーションを停止する最良の方法ですSparkストリーミングアプリケーションですが、完璧ではありません。適切なシャットダウンを実行する方が良いでしょうすべてのストリームレシーバーを停止し、ストリーミングコンテキストを停止しますが、個人的にはその方法がわかりません。
8
vanekjar

私はついにsparkストリーミングジョブを安全に閉じる方法を考え出しました。

  1. ソケットサーバースレッドを書き込み、ストリーミングコンテキストの停止を待機します
パッケージxxx.xxx.xxx 
 
 import Java.io. {BufferedReader、InputStreamReader} 
 import Java.net。{ServerSocket、Socket} 
 
 import org.Apache.spark.streaming.StreamingContext 
 
 object KillServer {
 
 class NetworkService(port:Int、ssc:StreamingContext) extends Runnable {
 val serverSocket = new ServerSocket(port)
 
 def run(){
 Thread.currentThread()。setName( "Zhuangdy |グレースフルを待機中ポート "+ポートで停止)
 while(true){
 val socket = serverSocket.accept()
(new Handler(socket、ssc))。run()
} 
} 
} 
 
 class Handler(socket:Socket、ssc:StreamingContext)extends Runnable {
 def run(){ 
 val reader = new InputStreamReader(socket.getInputStream)
 val br = new BufferedReader(reader)
 if(br.readLine()== "kill"){
 ssc.stop(true、true)
} 
 br.close(); 
} 
} 
 
 def run(port:Int、ssc:StreamingContext):Unit = {
(new NetworkService(port、ssc))。run 
} 
} 
  1. ストリーミングコンテキストを開始するmainメソッドで、次のコードを追加します

     ssc.start()
     KillServer.run(11212、ssc)
     ssc.awaitTermination()
  2. ヤーンにジョブを送信するためにspark-submitを記述し、後で使用するファイルに出力を送信します

 spark-submit --class "com.Mainclass"\
-conf "spark.streaming.stopGracefullyOnShutdown = true"\
-masteryarn-cluster --queue " root "\ 
-deploy-mode cluster\
-executor-cores 4 --num-executors 8 --executor-memory 3G\
 hdfs:/// xxx .jar>出力2>&1&
 
  1. 最後に、安全にシャットダウンsparkデータ損失や計算結果のないストリーミングジョブが持続しない!!!(ストリーミングコンテキストを正常に停止するために使用しているサーバーソケットがドライバーで実行されているため、出力をgrepします手順3でドライバアドレスを取得し、echo ncを使用してソケットキルコマンドを送信します)
 
#!/ bin/bash 
 driver = `cat出力| grep ApplicationMaster | grep -Po '\ d +。\ d +。\ d +。\ d +' `
 echo" kill "| nc $ driver 11212 
 driverid = `yarn application -list 2>&1 | grep ad.Stat | grep -Po'application_\d + _\d + '`
 yarn application -kill $ driverid 
 
2
pinkdawn
  1. あなたのデータソースは何ですか? Kafkaダイレクトレシーバーのように信頼できる場合は、ヤーンキルシャットダウンで問題ありません。アプリケーションを再起動すると、最後の完全なバッチオフセットから読み取ります。データソースの信頼性が低い場合、または正常なシャットダウンを自分で処理する場合は、ストリーミングコンテキストに何らかの外部フックを実装する必要があります。私は同じ問題に直面し、停止ボタンとして機能する新しいタブをwebuiに追加するための小さなハックを実装することになりました。
1
Fabien COMTE

最後のパズル要素は、YARNに適切な方法でデプロイされたストリーミングアプリケーションを停止する方法ですSpark YARNアプリケーションを停止(または強制終了)するための標準的な方法は、コマンドyarn application -kill [applicationId]を使用することです。そして、このコマンドはSparkストリーミングアプリケーションを停止しますが、これはバッチの途中で発生する可能性があります。したがって、ジョブがKafkaからデータを読み取る場合、処理結果をHDFSに保存し、最後にKafkaオフセットは、オフセットをコミットする直前にジョブが停止したときに、HDFSでデータが重複することを予期する必要があります。

グレースフルシャットダウンの問題を解決する最初の試みは、シャットダウンフックでSparkストリーミングコンテキスト停止メソッドを呼び出すことでした。

sys.addShutdownHook {
    streamingContext.stop(stopSparkContext = true, stopGracefully = true)
}

残念ながら、シャットダウンフックの呼び出しが遅すぎて、開始されたバッチを終了できず、Sparkアプリケーションがほぼ即座に強制終了されます。さらに、シャットダウンフックがJVMによって呼び出される保証はまったくありません。

このブログ投稿を書いている時点で、正常にシャットダウンする唯一の確認された方法Spark YARNでのストリーミングアプリケーションは、計画されたシャットダウンについて何らかの方法でアプリケーションに通知し、プログラムでストリーミングコンテキストを停止することです(ただし、シャットダウンからではありません)フック)。コマンドyarn application -killは、通知されたアプリケーションが定義されたタイムアウト後に停止しなかった場合の最後の手段としてのみ使用する必要があります。

アプリケーションは、HDFS上のマーカーファイルを使用して(最も簡単な方法)、またはドライバーに公開されている単純なSocket/HTTPエンドポイントを使用して(洗練された方法)、計画されたシャットダウンについて通知できます。

私はKISSの原則が好きなので、以下に、開始/停止するためのシェルスクリプトの擬似コードを見つけることができますSparkマーカーファイルを使用したスト​​リーミングアプリケーション:

start() {
    hdfs dfs -touchz /path/to/marker/my_job_unique_name
    spark-submit ...
}

stop() {
    hdfs dfs -rm /path/to/marker/my_job_unique_name
    force_kill=true
    application_id=$(yarn application -list | grep -oe "application_[0-9]*_[0-9]*"`)
    for i in `seq 1 10`; do
        application_status=$(yarn application -status ${application_id} | grep "State : \(RUNNING\|ACCEPTED\)")
        if [ -n "$application_status" ]; then
            sleep 60s
        else
            force_kill=false
            break
        fi
    done
    $force_kill && yarn application -kill ${application_id}
}

Sparkストリーミングアプリケーションでは、バックグラウンドスレッドはマーカーファイルを監視する必要があり、ファイルが消えたらコンテキスト呼び出しを停止します

streamingContext.stop(stopSparkContext = true, stopGracefully = true)

また、参照することもできます http://blog.parseconsulting.com/2017/02/how-to-shutdown-spark-streaming-job.html

0
Kishore