版本信息
Cloudera Express 6.3.1
Java VM 名称: Java HotSpot(TM) 64-Bit Server VM
Java 版本: 1.8.0_181
ResourceManager version: 3.0.0-cdh6.3.2
Hadoop version: 3.0.0-cdh6.3.2
现象
- 收到 CDH 监控系统发出的 Yarn ResourceManager 组件处于不健康状态的告警,登录平台查看 Yarn ResourceManager 组件的状态,看到 GC 持续时间不良 的提示。详细信息如下:
The health test result for RESOURCE_MANAGER_GC_DURATION has become bad: Average time spent in garbage collection was 46.8 second(s) (78.05%) per minute over the previous 5 minute(s). Critical threshold: 60.00%.
- 进入图表生成器查看 Java GC 回收时间情况
select jvm_gc_time_ms_rate
最近 7 天内主备 ResourceManager 的 GC 回收时间均值分别为 262ms 和 151ms,而其它正常组件 GC 时间都在微秒级别。
- 查看 Java 堆内存使用情况
select jvm_heap_used_mb
从主备实例堆内存使用情况看是非常典型的 内存泄露 问题。
产生告警的主实例已经基本回收不了内存了,垃圾回收时间和频率都较高,
所以触发了告警条件,如果放任不管后续没多久必然发生 OOM 崩溃。
处理
内存泄露解决办法最快且简单的办法就是重启,但是治标不治本。于是先重启了已经产生告警的实例,解决告警问题。 同时保留了另一个实例暂时不重启用于定位具体问题。
Google 检索相关问题
初步判断是内存泄露问题,具体是什么问题,尚未确定。通过 Google 搜索相关信息,关键词: cdh 6.3.1 yarn resourcemanager memory leak ,
找到了 CDH 6.3.4 版本的问题修复列表 : Fixed Issues in CDH 6.3.4 | 6.x - Cloudera Documentation (opens in a new tab)
其中 YARN-9639 - DecommissioningNodesWatcher cause memory leak 这一项可能与此问题相关。
Java 内存溢出问题定位
Google 检索到了可能相关的问题,但是还没办法确定 100% 相关。之前保留了一个实例用来定位问题,所以可以继续做分析。
- 定位问题进程号及进程所属用户
ps -ef | grep -i resourcemanager
# output:
# yarn 89416 89405 0 1月09 ? 00:17:13 /usr/java/jdk1.8.0_181-cloudera/bin/java -Dproc_resourcemanager...
得到进程号PID=89416, 进程用户UID=yarn,同时可知 Java 所在目录为 /usr/java/jdk1.8.0_181-cloudera/bin/java。
- jmap 输出堆内存信息到文件
sudo -u yarn /usr/java/jdk1.8.0_181-cloudera/bin/jmap -dump:format=b,file=/tmp/java_heap_map 89416
注意: 执行 jmap 命令打印堆内存信息时需要 sudo -u 切换到 Java 进程用户权限去执行,否则会报错:
89416: well-known file /tmp/.java_pid89416 is not secure: file should be owned by the current user (which is 0) but is owned by 984
- 复制输出的文件 /tmp/java_heap_map 到办公电脑进行分析
- 根据自己电脑系统和CPU架构下载安装 Eclipse Memory Analyzer (opens in a new tab)。 我这里用的是 m1 版的 macbook, 所以下载 Mac OSX (Mac/Cocoa/AArch64) (opens in a new tab) 版本安装。 这个工具可用于分析 Java 内存泄露问题,功能非常强大。
- 安装完打开软件,菜单 File -> Open Heap Dump... 打开前面 dump 出来的文件。 我们为 ResourceManager 分配的内存为2Gb, dump 出来的文件也接近 2Gb ,打开需要一定时间,耐心等待几分钟。
- 打开完成后,Details 下方可以看到堆内存存已使用 1.8G,点击 Actions 菜单中的 Top Consumers 进行分析。
- 分析完成后,得到下方分析结果。
查看 Biggest Top-Level Dominator Classes (Overview) 一栏,可以看到
class org.apache.hadoop.yarn.server.resourcemanager.DecommissioningNodesWatcher$PollTimerTask @ 0xaa3f89b0
这个类型的对象占了 1.6Gb(89%)。与前面检索到的 YARN-9639 - DecommissioningNodesWatcher cause memory leak 相吻合。
- 至此,已确定是 DecommissioningNodesWatcher 导致的内存泄露问题,与前面 Google 检索到的信息一致, 具体可以进这里 YARN-9639 (opens in a new tab) 查看详细报告。
总结
hadoop-yarn-server-resourcemanager 在 v3.1.0-RC1 版本被发现 DecommissioningNodesWatcher 存在内存泄露问题, 并在 3.3.0, 3.2.1, 3.1.3 等版本完成了修复。
对应的 CDH 6.3.1 使用了 3.0.0 版本 hadoop-yarn 组件,存在该内存泄露问题。CDH 版本于 6.3.4 版本完成修复。 升级版本可以解决这个问题,但是 CDH 于 6.3.3 版本开始不再支持 Cloudera Express 免费 License。 要升级上去需要购买更新 Cloudera Enterprise or CDP license。涉及到购买费用那就不太好申请了, 问题影响也不大,我们的 ResourceManager 实例分配了 2Gb 内存, 稳定运行了大半年才接近这个内存上限。同时架构上存在主备实例可以容忍单点故障, 于是写个定时任务每月重启一遍就可以规避掉 OOM 的可能了,同时向上层及业务反馈该问题的存在并记录。