如何在 Amazon EMR 中解决“java.lang.OutOfMemoryError:超过 GC 开销限制”例外?

上次更新时间:2019 年 10 月 10 日

Amazon EMR 中的 NameNode 服务失败,并显示下列例外:“java.lang.OutOfMemoryError:超过 GC 开销限制”。

简短描述

NameNode 服务使用内存来存储 HDFS 中所存储的文件的空间名对象和元数据。您在 HDFS 中的文件越多,NameNode 使用的内存越多。“java.lang.OutOfMemoryError:超过 GC 开销限制”错误表示 NameNode 堆的大小不足,无法容纳集群中的 HDFS 数据量。增加堆大小以防止出现内存不足例外。

解决方法

检查日志以确认错误

1.    使用 SSH 连接到主节点

2.    在主节点上运行以下命令以检查 NameNode 服务的状态:

initctl list

下面的输出表示 NameNode 服务已停止:

hadoop-hdfs-namenode stop/waiting

3.    检查以下路径中的 NameNode 日志以确认 OutofMemory 例外:/var/log/hadoop-hdfs/hadoop-hdfs-namenode-ip-xxxx.out。将 xxxx 替换为主节点的私有 IP 地址(例如:/var/log/hadoop-hdfs/hadoop-hdfs-namenode-ip-10-0-1-109.out)。

与此类似的输出可确认 NameNode 服务由于 OutOfMemory 例外而失败:

# java.lang.OutOfMemoryError: GC overhead limit exceeded
# -XX:OnOutOfMemoryError="kill -9 %p
kill -9 %p

增加 NameNode 堆大小

重要提示:此配置更改需要重启 NameNode 服务。请确保进行更改时未执行 HDFS 读取或写入操作。

对于 Amazon EMR 发行版本 5.21.0 及更高版本:

要增加堆大小,为正在运行的集群上的实例组提供一个 hadoop-env 配置对象。或者,启动新集群时添加配置对象。下面的配置对象可将堆大小从 1 GB 增加到 2 GB。选择适合您的工作负载的大小。

[
  {
    "Classification": "hadoop-env",
    "Properties": {
      
    },
    "Configurations": [
      {
        "Classification": "export",
        "Properties": {
          "HADOOP_NAMENODE_HEAPSIZE": "2048"
        },
        "Configurations": [
          
        ]
      }
    ]
  }
]

Amazon EMR 应用您的新配置,并适时地重启 NameNode 进程。

对于 Amazon EMR 发行版本 5.20.0 及更低版本:

1.    使用 SSH 连接到主节点

2.    在 /etc/hadoop/conf/hadoop-env.sh 文件中,增加 NameNode 堆大小。选择适合您的工作负载的大小。示例:

export HADOOP_NAMENODE_HEAPSIZE=2048

3.    保存更改。

4.    重启 NameNode 服务:

sudo stop hadoop-hdfs-namenode
sudo start hadoop-hdfs-namenode

5.    确认 NameNode 进程正在运行:

initctl list

成功的输出如下所示:

hadoop-hdfs-namenode start/running, process 6324

6.    确认 HDFS 命令正常工作:

hdfs dfs -ls /

成功的输出如下所示:

Found 4 items
drwxr-xr-x   - hdfs hadoop          0 2019-09-26 14:02 /apps
drwxrwxrwt   - hdfs hadoop          0 2019-09-26 14:03 /tmp
drwxr-xr-x   - hdfs hadoop          0 2019-09-26 14:02 /user
drwxr-xr-x   - hdfs hadoop          0 2019-09-26 14:02 /var