天天看點

記一次Azkaban任務報錯:unable to create native thread

在一次更新環境資訊任務中,需要重新開機Azkaban排程系統,重新開機後經常有任務出現如下報錯

現象: java.lang.OutOfMemoryError: unable to create new native thread,報錯的原因有很多種,有的是不能建立spark的context對象,有的是不能啟動spark webUI,但最終的棧資訊都是java.lang.OutOfMemoryError: unable to create new native thread.

在報錯的時候有一次我剛好在檢視原因,錯誤發出來就去檢視了一下yarn節點和Azkaban節點,發現記憶體很充足.是以可以直接排除硬體設施不足的原因.

java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:714)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:950)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1357)
at org.apache.spark.rpc.netty.Dispatcher$$anonfun$1.apply$mcVI$sp(Dispatcher.scala:198)
at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:141)
at org.apache.spark.rpc.netty.Dispatcher.<init>(Dispatcher.scala:197)
at org.apache.spark.rpc.netty.NettyRpcEnv.<init>(NettyRpcEnv.scala:54)
at org.apache.spark.rpc.netty.NettyRpcEnvFactory.create(NettyRpcEnv.scala:449)
at org.apache.spark.rpc.RpcEnv$.create(RpcEnv.scala:53)
at org.apache.spark.SparkEnv$.create(SparkEnv.scala:253)
at org.apache.spark.SparkEnv$.createDriverEnv(SparkEnv.scala:193)
at org.apache.spark.SparkContext.createSparkEnv(SparkContext.scala:289)
at org.apache.spark.SparkContext.<init>(SparkContext.scala:462)
at org.apache.spark.repl.SparkILoop.createSparkContext(SparkILoop.scala:1027)
at $iwC$$iwC.<init>(<console>:15)
at $iwC.<init>(<console>:25)
at <init>(<console>:27)
at .<init>(<console>:31)
           

    最開始以為是在淩晨跑批的過程中,因為任務量比較大,Azkaban叢集的記憶體不足了,是以調整了一下啟動任務的時間,但是錯誤繼續出來,沒有改善.

    後來檢視了一下這幾個機器上運作的程式,發現有的spark submit任務已經運作了兩天多了,跟我重新開機Azkaban的時間比較吻合,SO,殺掉這些僵屍程序.  Spark submit程式在啟動時,Driver啟動在本地,大任務的Driver記憶體會申請的比較多,雖然沒有worker節點在跑任務,但是driver不停止,申請的資源還是占着的,雖然可用記憶體充足但是不能配置設定出去,會導緻我現在遇到的這個錯誤.

做了如上更改後,有了一些改善,報錯的程式變少了,但根本原因還是沒有找到.

在網上搜,基本上都是講Linux系統允許建立的最大線程數不夠了,需要加大線程數,可是我的伺服器線程數本身就是40960,是滿足正常任務需求的.

繼續在網上查,偶然間看到這麼一條:

記一次Azkaban任務報錯:unable to create native thread

    感覺他講的很有道理,如果一個程序是另一個程序的子程序,父程序維護子程序清單的記憶體區域不夠用了,也會報這個錯誤.我們現在的問題和這個是有關系的.在大量任務執行時,每個啟動的任務都是Azkaban Executor的子程序,如果Executor的記憶體不夠啟動如此多的子程序,符合第一條描述的狀況.

檢視Azkaban的啟動腳本,關鍵部分如下:

if [ -z $AZKABAN_OPTS ]; then
  AZKABAN_OPTS="-Xmx3G"
fi
AZKABAN_OPTS="$AZKABAN_OPTS -server -Dcom.sun.management.jmxremote -Djava.io.tmpdir=$tmpdir -Dexecutorport=$executorport -Dserverpath=$serverpath -Dlog4j.log.dir=$azkaban_dir/logs -Dlog4j.configuration=$azkaban_dir/conf/log4j.properties"

java $AZKABAN_OPTS $JAVA_LIB_PATH -cp $CLASSPATH azkaban.execapp.AzkabanExecutorServer -conf $azkaban_dir/conf [email protected] &

echo $! > $azkaban_dir/currentpid
           

可以看到,啟動時-Xmx參數設定了3G的大小,問題可能确實出在這裡,因為這個伺服器本身隻有Azkaban在運作,直接改成了8G,不會影響其他服務.

改變後,重新開機Azkaban,觀察了兩天,沒有繼續出現問題.該問題解決.