Yarn ResourceManager GC overhead limit exceeded

語言: CN / TW / HK

本文已參與「新人創作禮」活動,一起開啟掘金創作之路

Yarn ResourceManager GC overhead limit exceeded

問題

```bash FATAL yarn.YarnUncaughtExceptionHandler (YarnUncaughtExceptionHandler.java:uncaughtException(51)) - Thread Thread[Timer for 'ResourceManager' metrics system,5,main] threw an Error. Shutting down now... java.lang.OutOfMemoryError: GC overhead limit exceeded at java.util.ArrayList.iterator(ArrayList.java:840) at org.apache.hadoop.metrics2.source.JvmMetrics.getGcUsage(JvmMetrics.java:134) at org.apache.hadoop.metrics2.source.JvmMetrics.getMetrics(JvmMetrics.java:103) at org.apache.hadoop.metrics2.impl.MetricsSourceAdapter.getMetrics(MetricsSourceAdapter.java:199) at org.apache.hadoop.metrics2.impl.MetricsSystemImpl.snapshotMetrics(MetricsSystemImpl.java:420) at org.apache.hadoop.metrics2.impl.MetricsSystemImpl.sampleMetrics(MetricsSystemImpl.java:407) at org.apache.hadoop.metrics2.impl.MetricsSystemImpl.onTimerEvent(MetricsSystemImpl.java:382) at org.apache.hadoop.metrics2.impl.MetricsSystemImpl$4.run(MetricsSystemImpl.java:369) at java.util.TimerThread.mainLoop(Timer.java:555) at java.util.TimerThread.run(Timer.java:505)

```

解決辦法

最簡單有效的修改ResourceManager Java heap size 增加即可,我是這麼解決的

分析(網上一大堆但是解決方法都不行,這裡copy一個分析比較好的)

1.最先想到的是由於記憶體洩漏導致,因此到叢集上取Dump檔案,最開始使用的是命令(jmap

-dump:live,format=b,file=dump.hprof 22439)獲取dump檔案的,但是導致的一個結果就是把ResourceManager搞掛了,後來才知道是因為探索環境的yarn使用的是G1垃圾回收機制,對於G1垃圾回收機制,使用上面的方式可能會將程序搞掛掉,改成下面的命方式即可成功的獲取dump檔案:jmap-J-d64 -dump:live,format=b,file=yarn-22439.dump 22439 。

2.通過對dump檔案的記憶體洩漏檢測分析,發現

在類AsyncDispatcher中的一個屬性(BlockingQueue eventQueue)的物件佔用了大量的記憶體,因此懷疑是該物件發生了記憶體洩漏。

  1. 通過類AsyncDispatcher的原始碼,發現其內部類GenericEventHandler會在處理訊息的時候將上面懷疑是記憶體洩漏的物件eventQueue的size打印出來,因此決定檢視線上yarn的日誌,看此佇列的長度

下圖是列出的佇列的長度,可明顯可以看出該佇列的尺寸達到了上千萬,這肯定是有問題的。而正常的大叢集的日誌中佇列的長度只有幾千,很明顯該物件是有問題的。

4.再通過記憶體分析工具發現,上述有異常的佇列中存放的都是ContainerFinishedEvent和ContainerCreatedEvent物件,因此去檢視該物件是在哪被建立和消費的。

  1. 通過對原始碼進行分析定位到ContainerFinishedEvent事件是在類SystemMetricsPublisher中被消費掉的,該類是將ContainerFinishedEvent封裝成TimelineEntity實體之後通過Http的post方式傳送給yarn的TimelineServer程序。

  2. 綜上分析,目前的主要原因是由於消費者(也就是往TimelineServer傳送Event事件資料)傳送資料的能力不夠,導致訊息佇列中快取的大量的訊息,隨著時間的推移,訊息資料不斷增多,從而導致yarn記憶體不夠用,從而需要重啟。

分析原文地址他這裡給出了2種方案我都沒用,因為我們背景不太一樣,他是執行一段時間後就不行,大家可以參考一下,他的分析有圖,我覺得還是因為記憶體不夠參會出線這個問題,我是加了記憶體,因為我本來就沒有把機器的記憶體全部分給yarn,一看是隻分了60% ,後面處理一些必須用的,幾乎給yarn分滿了,就好了