記錄一次服務器重啓後sparkStreaming任務啓動失敗原因及排查過程

因特殊原因公司服務器從晚上6點開始CPU資源使用率飆升至100%
在這裏插入圖片描述

然後運維重啓服務器,重新構建此服務器上所有作業

然而第二天早上查看日誌發現,有一個job作業啓動失敗,經過一系列排查最終解決,特此記錄一下

此作業是sparkStreaming 讀取kafka topic並存儲至hbase ,offset保存在zookeeper;
此問題並非是常見的offset過期或offset不一致問題; 請往下看

爲了避免是代碼問題,首先在自己搭建的測試環境中運行沒有問題
後放到生產環境中直接報錯

報錯內容 :
Job aborted due to stage failure: Aborting TaskSet 0.0 because task 5 (partition 5) cannot run anywhere due to node and executor blacklist. Blacklisting behavior can be configured via spark.blacklist.*.
在這裏插入圖片描述
翻譯:
*由於階段失敗而中止的作業:由於節點和執行者黑名單,任務5(分區5)無法在任何地方運行,正在中止任務集。黑名單行爲可以通過spark.blacklist.配置。

錯誤顯示任務5無法在任何地方運行,所以終止所有任務,後面還跟了一個黑名單配置
後上 谷歌查詢,有一篇文章詳細解釋了spark黑名單機制,鏈接如下:
[https://www.jianshu.com/p/8af15cb644ef]

文章內容簡單來講就是:
• 有個節點上的磁盤由於某些原因出現間歇性故障,導致某些扇區不能被讀取。假設我們的 Spark 作業需要的數據正好就在這些扇區上,這將會導致這個 Task 失敗。
• 這個作業的 Driver 獲取到這個信息,知道 Task 失敗了,所以它會重新提交這個 Task。
• Scheduler 獲取這個請求之後,它會考慮到數據的本地性問題,所以很可能還是把這個 Task 分發到上述的機器,因爲它並不知道上述機器的磁盤出現了問題。
因爲這個機器的磁盤出現問題,所以這個 Task 可能一樣失敗。然後 Driver 重新這些操作,最終導致了 Spark 作業出現失敗
在這裏插入圖片描述

於是開始懷疑是機器故障或者kafka分區損壞等可能,但經過排查發現kafka分區正常:
在這裏插入圖片描述

服務器集羣運行亦正常,況且公司使用的CDH 5.14版本,對應的spark是1.6版本,根本沒有黑名單配置項,黑名單spark.blacklist.配置是在spark2.2.0版本後纔有的功能

隨排除了kafka及硬件問題的可能

後來想到spark提交作業的時候給了一個選項:
–spark.dynamicAllocation.enabled=true
在這裏插入圖片描述
指定是動態資源調配

爲了方便調錯於是去掉其他配置,直接改成最接地氣的啓動方式:
spark-submit --class com.shenque.start.KafkaZKManager --master yarn-client --executor-memory 1000M
–executor-cores 2 --num-executors 3 --driver-memory 1000M jar包名稱

啓動後 依然報錯,但是錯誤卻變了:
Container marked as failed: container_e18_1582561040524_1837_01_000002 on host: Exit status: 143. Diagnostics: Container killed on request. Exit code is 143
Container exited with a non-zero exit code 143
Killed by external signal
在這裏插入圖片描述

翻譯:
標記爲失敗的容器:Container_e18_1582561040524_1837_01_000002on退出狀態:143。診斷:應請求終止容器。出口代碼是143
容器以非零退出代碼143退出
被外部信號殺死

再次谷歌,於是找到下面這篇文章:
https://blog.csdn.net/yijichangkong/article/details/51332432

此文章雖然和我報錯的內容不太一樣,但是文中一句話提醒了我:
從hive報錯看是由於物理內存達到限制,導致container被kill掉報錯。

突然想到,從昨天下午6點到今天上午8點十多個小時,kafka有可能積壓了大量數據,內存空間不足導致任務失敗

於是增大內存,將executor-memory設置爲4G,將啓動腳本改爲:
spark-submit --class com.shenque.start.KafkaZKManager --master yarn-client --executor-memory 4000M
–executor-cores 2 --num-executors 6 --driver-memory 2000M jar包名稱

於是懷着期待的心啓動,發現依然報錯,錯誤和之前一樣:
在這裏插入圖片描述

爲了探究問題所在,於是開始一條一條看日誌,抽絲剝繭發現了一句話:
cluster.YarnClientSchedulerBackend: Disabling executor 1.
在這裏插入圖片描述

翻譯:
cluster.YarnClientSchedulerBackend:禁用執行器1。

一言以蔽之:Yarn把執行器給禁用了

繼續往下翻發現,發現所有的executor執行器都被禁用了:

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
最終鎖定問題出現在yarn上。但具體什麼原因,還不清楚

那乾脆就不用yarn來做資源管理,直接用spark-sumit local[6] 本地來執行程序

更改作業腳本:

spark-submit --class com.shenque.start.KafkaZKManager --master local[6] --executor-memory 4000M
–executor-cores 2 --num-executors 6 --driver-memory 2000M jar包名稱

然後奇蹟的一幕就發生了,運行成功 :
在這裏插入圖片描述

但你不可能讓程序一直運行在本地上,於是等了一會kill掉程序,再次部署到yarn上執行:
在這裏插入圖片描述

竟然也成功了:
在這裏插入圖片描述

於是明白了問題所在,在本地運行的時候spark將kafka上積壓的數據全部消費掉了

而此時再運行yarn上的時候不需要太大內存就可以成功

那麼我們之前調大了內存爲何運行還是失敗呢,經過一番查找資料發現,很有可能是公司的服務器中限制了Yarn的最大Container大小!

在hadoop2及以上版本中,task 是運行在container中的。
Yarn配置文件中會限制Container的最小內存(yarn.scheduler.minimum-allocation-mb)、最大內存(yarn.scheduler.maximum-allocation-mb)。
如果container的內存超限,會被yarn殺死。

所以之所以Yarn會殺死6個executor,很有可能是超過了設置的container內存閾值導致的
後來經過本地無yarn模式將積壓數據消費後,再用不超過container閾值的內存容量在Yarn上運行即會成功;

至此問題解決,特此記錄

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