上週一個 job 莫名奇妙的hang 在那里 20+ hour,9001 個tasks 完成了8999個,還有2個未完成。
點進去看task page,沒有發現running 的 task
發郵件問了社區。社區的人說可能是spark.scheduler.listenerbus.eventqueue.capacity設置太小。 在log stderr and stdout 發現了這句
grep "events from" stderr
20/05/05 16:00:39 WARN AsyncEventQueue: Dropped 2 events from executorManagement since Wed Dec 31 16:00:00 PST 1969.
是不是有點真相只有一個的感覺,似乎這running 2 tasks 和 Dropped 2 events 很有關連。下面來看看這段報錯代碼。看代碼之前,你要知道的一些基本知識:
1. what is spark listener? what is spark listener event?
我覺得這就是個監聽器和監聽事件的關係。 spark listener event 有 SparkListenerStageCompleted, SparkListenerTaskStart
....,太多了
2. what isLiveListenerBus
至於 liveListenerBus 這個就是listener 的集合站。開了一個Queue 來放所有的 listener。
報錯代碼的位置:https://github.com/apache/spark/blob/v2.3.1/core/src/main/scala/org/apache/spark/scheduler/AsyncEventQueue.scala#L152.
這段代碼的一些變量說明
1. 功能: 將一個event 加入處理隊列eventQueue
2.eventCount : event 的個數+1
3.eventQueue:將要處理的event 的加入eventQueue, 加入成功 eventQueue.offer(event) 函數結束
4.加入不成功,event 的個數重新-1, dropEvents(被扔掉的 events) +1. 然後打印出log說
有些listener 太慢了 跟不上發task 的scheduler 的速度,有意思的問題就在這裏
什麼叫listener 太慢了?程序能走到這裏的原因是 event queue capacity 太小了,處理不了這些event ,所以被扔掉。
但是你好好想想,爲什麼那兩個 SparkListenerTaskEnd的 event 要被扔掉呢? 因爲這兩個 task 的處理速度慢啊。 別的task
結束了都發送了SparkListenerTaskEnd. 所以提前被發送到了隊列里。 解決這個問題最快的辦法。把spark.scheduler.listenerbus.eventqueue.capacity 設置得大點(默認是10000)
logError(s"Dropping event from queue $name. "+
"This likely means one of the listeners is too slow and cannot keep up with"+
"the rate at which tasks are being started by the scheduler.")