問題:
線上的spark thriftserver運行一段時間以后,ui的executor頁面上顯示大量的active task,但是從job頁面看,並沒有任務在跑。此外,由於在yarn mode下,默認情況是一個executor只能有一個active task,但是executor頁面的active task卻可以有多個。而且在沒有任務在跑的情況下,動態資源你分配不能生效,spark thriftserver在空閑的情況下資源得不到釋放。
問題排查:
1,看到某個executor有大量的active task,首先想到是不是真的是task沒有結束。所以首先去對應的executor機器上,查看對應進程的cpu,發現利用率很低。與此同時,打印進程線程棧和正常的executor的線程棧進行對比,發現連行數都是一樣的。初步排除了是由於task沒有結束,導致task一直在忙的情況。
2,雖然是偶現,但是發現即使某個executor的active task已經很高了(比方說10,大於1),當有新的任務過來時,這個executor仍然可以調度在這個executor上。由此可以確定,在driver內部的dagscheuler和task scheduler中對資源使用情況的相關統計數據是對的。
3,通過1,2的分析,接下來的猜測就是UI顯示的數據不對了。2.3以后對ui的模塊進行了重新改造,難道是新引入的bug?從官方的jira上搜了一圈,沒有發現類似的問題。
4,除了UI上顯示的active task不對,spark的動態資源分配也確實沒有生效(在沒有任務時,executor資源沒有釋放),說明動態資源分配時獲取的系統資源統計也是有誤的。於是找了一圈有關動態資源分配的一些jira,還真發現了一些jira(https://issues.apache.org/jira/browse/SPARK-11334)打上補丁,但是UI頁面顯示的active task肯定和這個issue是沒有關系的。
5,到此時,陷入了無解。后來突然想到,無論是UI頁面的統計還是動態資源分配,都走的是消息總線機制,之前看源碼的時候印象中,消息總線中的消息不是100%不丟的(spark Listener和Metrics機制),所以去日志中搜了一下相關消息,果然發現有消息丟失。
然后翻了一下源碼,spark消息這個隊列的大小是10000,超過這個值的時候,如果還沒有消費掉,就會丟棄消息,然后果斷調大到10w,目前已過去三四天了,線上還沒有出現這個問題,應該就是這個原因了。
6,進一步思考,為啥會有這個的消息事件呢?spark官方並沒有類似的jira,然后想到我們自己跑的spark自行添加了一些event到消息總線,可能是自行添加的event導致的,所以以后自行添加event事件的時候要注意一下這個隊列大小的限制。另外,在100%需要對數據進行統計的准備的情況下,使用spark內部的消息總線機制來做異步處理並不是非常的恰當。