私は何時間も実験とグーグルをしてきましたが、運がありませんでした。
ローカル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」はそれを停止するための好ましい方法ですか?
spark-submit
コンソールを閉じることができます。書き込み[〜#〜]実行中[〜#〜]状態のとき、ジョブはすでにバックグラウンドで実行されています。yarn application -kill
はおそらくストリーミングアプリケーションを停止する最良の方法ですSparkストリーミングアプリケーションですが、完璧ではありません。適切なシャットダウンを実行する方が良いでしょうすべてのストリームレシーバーを停止し、ストリーミングコンテキストを停止しますが、個人的にはその方法がわかりません。私はついにsparkストリーミングジョブを安全に閉じる方法を考え出しました。
パッケージ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 } }
ストリーミングコンテキストを開始するmain
メソッドで、次のコードを追加します
ssc.start() KillServer.run(11212、ssc) ssc.awaitTermination()
ヤーンにジョブを送信するために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&
#!/ 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
最後のパズル要素は、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