雲梯開發人員在雲梯Yarn集群的搭建和維護過程中做了許多工作,本文選擇這期間部分較為典型的問題,通過對這些問題的分析和解決方案,為大家分享分布式系統問題調查的經驗。
調查的問題
1. 2013年初引入社區0.23時,調查ResourceManager運行過程匯總突然掛掉的問題
現象:監控報警,線上運行的RM突然掛掉,RM異常日志如下,
2012-12-17 17:20:28,294 FATAL org.apache.hadoop.yarn.server.resourcemanager.ResourceManager: Error in handling event type APP_REMOVED to the scheduler
java.lang.NullPointerException
at org.apache.hadoop.yarn.server.resourcemanager.scheduler.SchedulerApp.unreserve(SchedulerApp.java:390)
at org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler.completedContainer(FairScheduler.java:590)
at org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler.removeApplication(FairScheduler.java:546)
at org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler.handle(FairScheduler.java:871)
at org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler.handle(FairScheduler.java:80)=
at org.apache.hadoop.yarn.server.resourcemanager.ResourceManager$SchedulerEventDispatcher$EventProcessor.run(ResourceManager.java:340)
at java.lang.Thread.run(Thread.java:662)
處理方法:啟動RM繼續提供服務,記錄bug,開始調查。
調查過程:社區暫無此問題,需要自己分析。
a.分析,查看異常之前的代碼,還發現一些其他異常,Error in handling event type NODE_UPDATE to the scheduler,RM的調度器處理Node更新的時候出現NPE,根據異常和代碼判斷出在AppSchedulable#assignContainer中 在reserved=true的情況下,獲取的container的priority和傳入的priority不一致導致的。通俗的講,就是調度器有預訂機制,另外在分配資源的時候每個container都有優先級,如果一個應用有在一個NM上預訂一個優先級為X的container,另外一個等待的container優先級為更高的Y,當這個NM發生心跳給RM說,可以向它調度一個container,這時調度器本想找一個優先級更高的Y調度到該節點上,卻沒有找到,導致NPE。
解決方案:調度器應該優先找一個已經預訂在該節點上的container分配給該節點,其次才是選擇高優先級的container。不過就在我們調查出並解決的時候Apache Hadoop社區也剛好遇到並提供解決方案,因此最終沒有貢獻給社區。
2. 調查某些情況下RM不調度的問題
現象:RM能接收提交的作業,但是集群中所有作業都無法被調度,日志也沒有異常。
調查過程:Dump出RM的進程棧,發現RM處於死循環狀態。查看死循環部分的代碼,原因是 調度器每次分配一個container給NM,然后對app排序,繼續下一次的分配,如果調度器只是把container預訂到該NM上,調度器沒有調度任務給該NM,對app排序,進行下一次分配,這樣就RM進入了死循環,無法工作。
解決方案:如果把某個container預訂到NM上,也應該認為分配了相應的任務,退出循環。貢獻給社區,YARN-300。
3. 調查RM異常退出的問題
現象:監控報警,線上運行的RM突然掛掉,RM異常日志如下:
2012-12-30 17:14:17,171 FATAL org.apache.hadoop.yarn.server.resourcemanager.ResourceManager: Error in handling event type NODE_UPDATE to the scheduler
java.util.ConcurrentModificationException
分析過程:異常是兩個線程同時對一個對象進行操作,一個線程有加鎖,另外一個線程沒有加鎖,導致異常的出現。
解決方案:兩個線程都在調用該對象前加鎖。貢獻給社區,YARN-301
4. 調查網頁上顯示FairScheduler調度資源不准確的問題
現象:RM網頁上顯示調度信息不准確,資源使用量越來越大,已經超過集群資源量(內存)。
原因:reserve的時候增加三次,unreserve的時候減少兩次,導致數字越來越大。
解決:reserve與unreserve應該相對應,增加多少就得減少多少。社區也有相應的問題,暫未貢獻給社區。
5. 客戶端提交作業后一直hang着,沒反應
現象:用戶提交一個作業到RM的某個組,但是RM上配置這個組不接受這個用戶作業,這時候客戶端一直hang這沒反應。
原因:原因是以為RM判斷出不允許的作業時,沒有做如何處理,導致客戶端一直hang着。
解決:增加處理機制,返回給客戶端相應的出錯信息。貢獻給社區 YARN-319。
還有一些RM掛掉的問題,社區剛好解決,我們直接引入,如
https://issues.apache.org/jira/browse/YARN-335 RM出現NPE掛掉
https://issues.apache.org/jira/browse/MAPREDUCE-4144 RM處理Node更新的時候出現NPE
6. 引入Cgroup使Yarn支持對CPU的調度和隔離。
問題:Spark應用是內存密集型,但是對CPU要求不高,而MPI對CPU要求多,只有內存的調度不夠。
設計:社區提供的Cgroup,支持CPU的隔離和調度。引入這部分后,我們遇到一個比較嚴重的問題,它要求NM創建賬戶,這從運維角度上來說是不可行的,它的目的是為了安全性,但是對內部應用來說必要性不大,另外Cgroup對CPU的隔離不依賴多賬戶,因此通過修改一個container-executor.c,防止啟動container的時候修改賬戶,而是使用一個統一的賬戶運行container,即能滿足安全需要,又能減少運維人員的工作量。
7. MRApplicationMaster初始化性能優化
問題:MRApplicationMaster初始化很慢。
分析:通過調查發現慢在解析rack上,由於集群大,datanode多,MRApplicationMaster啟動的時候會初始化map task,這時候會頻繁調用解析腳本,導致初始化慢,嚴重影響作業的運行時間
解決方案:通過在每個NM上增加一個包含所有datanode的機器名和rack對應信息的文件,MRApplicationMaster啟動的時候讀取這個文件,防止頻繁調用解析腳本,大大加快了作業初始化速度。
經驗總結
Hadoop類似的分布式開源框架,出問題還是比較常見的,關鍵是出問題后如何解決,
a. 一般情況下首先到社區尋找類似的問題,如果已經解決則直接引入即可
b. 如果社區沒有解決,那么就需要自己分析,如果是bug問題,則需要通過分析日志和代碼,最好能在測試集群上重現相應的問題,若能重現,則通過遠程調試或增加打印日志的方式分析相應的問題。找到原因后解決方案則是多種多樣的,要結合自己的實際情況選擇解決方案。
c. 如果是性能問題,則需要分析性能瓶頸,慢在哪一塊,慢在哪一步,慢在哪行代碼,多向自己提出這幾個問題,則能一步步的定位性能瓶頸,然后就需要創新性的提出一些優化方案。
所以在分布式應用中,無論是bug調查還是性能問題,關鍵都在於定位原因,原因找到后解決才能確定解決方案。