一次spark作業執行後進程無法關閉的原因及解決方案

最近運維的同學頻頻反映,spark集羣作業模式,每次執行完成spark的進程端口都已經關閉了,但是通過命令執行spark作業的進程和端口卻無法自動關閉,嚴重影響其他業務組的作業運行,但是無法關閉的情況不是經常出現,出現頻率也不規範,但是執行任務正常,數據清洗加工正常,存儲正常,查看日誌發現是在作業執行完成會執行sparksession.stop方法,是這個方法堵塞了進程的正常關閉,但是原因從日誌上無法分析,考慮從jvm層面進行分析查看,是否是因爲內存或者cpu的原因導致,用-jstack -pid 命令進行打印jvm的堆棧:

只複製部分堆棧:

從堆棧上大致可以看出是main函數的sparksession.stop的線程堵塞了,線程的幾種狀態在這就不細說了,大家可以自己在google和百度自行查找,但是是什麼原因的,仔細一看發現是在等待某個鎖的釋放,但是爲什麼會被鎖住呢,只能在stop的方法進行查看源碼分析了:

看到synchronized關鍵字大概能明白了,應該是鎖住了,所以尋找鎖住的原因,在堆棧中進行find發現了這樣的一個線程信息

一看原來是這個線程獲取到了鎖,但是爲什麼進行waiting呢,這個是將要解決的問題了,仔仔細細的看了下,發現應該是跟spark的ContextCleaner有關,這個方法是用來清理內存空間的殘留數據,但是它本是個守護線程,並且在作業運行過程中就已經進行清理了,難道是因爲一直在清理內存,但仔細想來也不會,因爲如果一直在清理空間的話,守護線程怎麼會waiting呢,所以又看了一遍發現又找到一個可以看懂的內容:

at org.apache.spark.rpc.RpcTimeout.awaitResult(RpcTimeout.scala:81)

Rpc協議超時?原來是spark進行心跳檢測通信的時候超時了,但是詢問運維的同學,在堵塞的期間,並沒有網絡異常報警或者內存空間佔滿報警,所以應該不是這2個原因,然後google了一下,發現大佬們基本給出2個答案:

1)spark節點宕機了(當然不可能)

2)引發這個問題是由於數據發生了傾斜,導致STW,縮短GC時間可以解決

所以在spark的啓動命令加入動態conf參數:

--conf "spark.driver.extraJavaOptions=-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseConcMarkSweepGC

--conf "spark.executor.extraJavaOptions=-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseConcMarkSweepGC

使用了CMS的回收站(jvm參數配置的簡單,也可以配置新生代老年代的內存空間,以及回收站),同時修改了spark.network.timeout 從36s改爲默認120s,目前運行幾天並沒有出現以往情況,心裏有點竊喜,哈哈,但是不確定是否是因爲此原因,所以有明確處理經驗的朋友可以留言給我,感謝!。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章