記一次yarn導致cpu飆高的異常排查經歷
yarn就先不介紹了,這次排坑經歷還是有收穫的,從日誌到堆疊資訊再到原始碼,很有意思,下面聽我說
問題描述:
叢集一臺NodeManager的cpu負載飆高。
程序還在但是看日誌已經不再向ResourceManager傳送心跳,不斷重複下文2的動作。
心跳停止一段時間後會重連上RM但是cpu仍然很高,再過一段時間心跳再停,一直迴圈。
NodeManager的日誌解析
1.NM的localizing過程
localizing:container開始從hdfs下載resource,hdfs檔案的狀態從INIT變成DOWNLOADING。
2018-08-25 16:15:38,592 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.LocalizedResource:Resource hdfs://mycluster/user/hdfs/.staging/application_1444990016246_29569/libjars/avro-mapred-hadoop2.jar transitioned from INIT to DOWNLOADING
2.無法刪除
這裡異常開始了。
container在localizing過程中被stop或者kill,導致hdfs檔案狀態保持為DOWNLOADING。
non-zero refcount表示當前沒有其他container在使用這個資源,說明這個資源將無法刪除。
2018-08-25 19:15:38,592 ERROR org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.LocalResourcesTrackerImpl: Attempt to remove resource: { { hdfs://mycluster/user/hdfs/.staging/application_1444990016246_29569/libjars/avro-mapred-hadoop2.jar, 1448139497492, FILE, null },pending,[],920074451410033,DOWNLOADING} with non-zero refcount
3.CancellationException
任務已經被kill所以報了CancellationException
2018-08-25 19:25:34,592 WARN org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.ResourceLocalizationService: {...}failed;
java.util.concurrent.CancellationException
4.恢復
一段時間後狀態從DOWNLOADING轉為FAILED,hdfs資源可以刪除
2018-08-25 20:15:38,592 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.LocalizedResource:Resource hdfs://mycluster/user/hdfs/.staging/application_1444990016246_29569/libjars/avro-mapred-hadoop2.jar(->/data/nm-local-dir/usercache/hadoop/filecache/5432524/avro-mapred-hadoop2.jar) transitioned from DOWNLOADING to FAILED
5.刪除
刪除本地快取的檔案(可能已損壞)
2018-08-25 19:15:38,592 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.LocalResourcesTrackerImpl:Removed /data/nm-local-dir/usercache/hadoop/filecache/5432524/avro-mapred-hadoop2.jar from localized cache
6.重新請求
請求的資源不在快取中,將重新請求
2018-08-25 19:15:38,592 INFO org.apache.hadoop.yarn.server.nodemanager.containermanager.localizer.LocalResourcesTrackerImpl:Container container_152345432_4324_3_4324234 sent RELEASE event on a resource request {hdfs://mycluster/user/hdfs/.staging/application_1444990016246_29569/libjars/avro-mapred-hadoop2.jar,,,} not present in cache
原因總結
container被stop,原因可能是與外部元件rpc失敗,或者任務被人為kill等等異常。導致hdfs資源異常無法刪除而container又會一直嘗試去刪除
解決辦法
1.Low的辦法:
手動刪除hdfs中無法刪除的檔案(難實現,不知道刪那些檔案且很多時操作麻煩)
2.高階的辦法:
找到異常的位置
LocalResourcesTrackerImpl(line339)
public boolean remove(LocalizedResource rem, DeletionService delService) {
// current synchronization guaranteed by crude RLS event for cleanup
LocalizedResource rsrc = localrsrc.get(rem.getRequest());
if (null == rsrc) {
LOG.error("Attempt to remove absent resource: " + rem.getRequest()
+ " from " + getUser());
return true;
}
if (rsrc.getRefCount() > 0
|| ResourceState.DOWNLOADING.equals(rsrc.getState()) || rsrc != rem) {
// internal error
LOG.error("Attempt to remove resource: " + rsrc
+ " with non-zero refcount");
return false;
} else { // ResourceState is LOCALIZED or INIT
localrsrc.remove(rem.getRequest());
if (ResourceState.LOCALIZED.equals(rsrc.getState())) {
delService.delete(getUser(), getPathToDelete(rsrc.getLocalPath()));
}
decrementFileCountForLocalCacheDirectory(rem.getRequest(), rsrc);
LOG.info("Removed " + rsrc.getLocalPath() + " from localized cache");
return true;
}
}
ResourceState.DOWNLOADING.equals(rsrc.getState())
檔案狀態為DOWNLOADING則報錯,可在原始碼中刪除這個條件。
參考新增補丁:
3.無敵的辦法:
重啟大法。。。重啟nodemanager,spark等任務會自動failover,不會影響線上的業務
總結
這個問題和資源分配或者container的資源佔用沒有關係,因為是nodemanager的cpu飆高,而不是container。
產生這個問題的原因是在剛提交任務的時候,container開始初始化並且開始從hdfs拉依賴資源到本地,此時任務掛了或者container掛了(人為的或者超時等原因)。
並且此時沒有其他container在使用這個資源,則這個資源就會保持在DownLoading狀態,則會報上面第二個錯誤。
正常情況下不用理會這個報錯,一段時間後會把DownLoading改為Failed,然後直接將資源刪除。
但是我這裡觀察到的情況是DownLoading狀態的檔案太多,狀態轉換速度非常慢,甚至一直都無法轉換成功,導致無法刪除,日誌裡出現大量類似2的報錯且把cpu拉得特別高偶爾出現nodemanager假死的情況。
最終的解決辦法是重啟。