如何为 Apache Hadoop NameNodes 启用 GC 日志记录,同时防止日志文件覆盖和限制磁盘空间使用

Posted

技术标签:

【中文标题】如何为 Apache Hadoop NameNodes 启用 GC 日志记录,同时防止日志文件覆盖和限制磁盘空间使用【英文标题】:How to enable GC logging for Apache Hadoop NameNodes, while preventing log file overwrites and capping disk space usage 【发布时间】:2016-10-04 18:27:27 【问题描述】:

我们最近决定在多个集群(具体版本不同)上为 Hadoop NameNode 启用 GC 日志记录,以帮助调查与 NameNode 相关的内存和垃圾收集问题。我们希望集群中的所有 NameNode(活动和备用或主要和辅助)都使用此功能。我们还想避免两个我们知道可能会发生的问题:

NameNode 因任何原因重新启动时覆盖日志文件 日志占用过多磁盘空间,导致磁盘被填满

当一个进程的 Java GC 日志记录开始时,它似乎会替换任何同名文件的内容。这意味着除非您小心,否则您将丢失 GC 日志记录,也许在您更可能需要它的时候。

如果您让集群运行足够长的时间,日志文件将填满磁盘,除非进行管理。即使 GC 日志记录目前不是很庞大,我们也希望管理出现异常情况的风险,这种情况会导致记录率飙升。

【问题讨论】:

【参考方案1】:

有几个环境变量可以在 hadoop-env.sh 中设置,以便在 NameNode 启动时传递 JVM 参数:

HADOOP_OPTS(适用于所有已启动的客户端和服务器调用 使用“hadoop”,甚至是“hadoop dfs”) HADOOP_NAMENODE_OPTS(使用 NameNode HA 会影响活动和备用 NameNode,没有 NameNode HA 会影响主 NameNode) HADOOP_SECONDARYNAMENODE_OPTS(影响辅助NameNode,如果没有NameNode HA)

这个问题专门针对 NameNode,因此我们希望将 JVM 参数添加到 HADOOP_NAMENODE_OPTSHADOOP_SECONDARYNAMENODE_OPTS(如果相关)。现在让我们讨论要包含在其中的 JVM 参数。

要启用对文件的 GC 日志记录,您需要添加 -verbose:gc -Xloggc:<log-file-location>

您需要特别考虑日志文件名,以防止在 NameNode 重新启动时被覆盖。似乎每次调用都需要一个唯一的名称,因此附加时间戳似乎是最好的选择。您可以包含类似 `date +'%Y%m%d%H%M'` 的内容来添加时间戳。在此示例中,它的格式为 YYYYMMDDHHMM。在某些 Java 版本中,您可以将“%t”放在日志文件位置,它将被格式为 YYYY-MM-DD_HH-MM-SS 的 NameNode 启动时间戳替换。

现在开始管理磁盘空间的使用。如果有比我现有的更简单的方法,我会很高兴。

首先,利用 Java 内置的 GC 日志文件轮换。 -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M 是启用此轮换的示例,它拥有来自 JVM 的多达 10 个 GC 日志文件,每个文件的大小不超过 10MB。 10 x 10MB 是 100MB 的最大使用量。

使用最多 10 个文件的 GC 日志文件轮换,“.0”、“.1”、...“.9”将添加到您在 Xloggc 中提供的文件名中。 .0 将是第一个,在达到 .9 之后它将替换 .0 并以循环方式继续。在某些版本的 Java 中,'.current' 会附加在当前正在写入的日志文件名称的末尾。

由于我们显然必须避免覆盖的唯一文件命名,每个 NameNode 进程调用可以有 100MB,因此这不是管理 NameNode GC 日志使用的磁盘空间的完整解决方案.您最终会在每个 NameNode 服务器上获得一组多达 10 个 GC 日志文件——这可能会随着时间的推移而增加。最好的解决方案(在 *nix 下)似乎是使用 logrotate 实用程序(或其他一些实用程序)定期清理过去 N 天内未修改的 NameNode GC 日志。

请务必进行计算并确保您有足够的磁盘空间。

人们经常希望他们的 GC 日志中的详细信息和上下文比默认的更多,因此请考虑添加 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps

把这些放在一起,你可能会在 hadoop-env 中添加一些东西:

TIMESTAMP=`date +'%Y%m%d%H%M'`
# location/name prior to .n addition by log rotation
NAMENODE_GC_LOG_NAME="hdfs_log_dir_prefix/$USER/hdfs-namenode-gc.log-$TIMESTAMP"

NAMENODE_GC_LOG_ENABLE_OPTS="-verbose:gc -Xloggc:$NAMENODE_GC_LOG_NAME"
NAMENODE_GC_LOG_ROTATION_OPTS="-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M"
NAMENODE_GC_LOG_FORMAT_OPTS="-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps"

NAMENODE_GC_LOG_OPTS="$NAMENODE_GC_LOG_ENABLE_OPTS $NAMENODE_GC_LOG_ROTATION_OPTS $NAMENODE_GC_LOG_FORMAT_OPTS" 

它应该被插入到上面设置HADOOP_NAMENODE_OPTSHADOOP_SECONDARYNAMENODE_OPTS 的地方。然后将$HADOOP_NAMENODE_OPTS 添加到HADOOP_NAMENODE_OPTSHADOOP_SECONDARYNAMENODE_OPTS(如果存在)以代替任何现有的与GC 记录相关的参数。

在上面,您可以将hdfs_log_dir_prefix/$USER 更改为您希望 GC 日志到的任何位置(您可能希望它与 NameNode 日志位于同一个位置)。您也可以更改日志文件命名。

如果您使用 Apache Ambari 管理 Hadoop 集群,那么这些更改将位于 HDFS 服务 > 配置 > 高级 > 高级 hadoop-env > hadoop-env 模板中。使用 Ambari,hdfs_log_dir_prefix 将自动替换为定义在字段上方几行的 Hadoop 日志目录前缀。

GC 日志记录将在 NameNode 重新启动时开始发生。如果您有 NameNode HA 并且两个 NameNode 都在线,那么您可以一次重新启动一个而无需停机。

【讨论】:

编写了以下脚本以帮助验证所有 JVM 参数在运行的 NameNode 中是否正确设置:github.com/Symantec/verify-running-processes-jvm-flag-values。你可以运行类似:verify-running-processes-jvm-flag-values.sh NameNode UseGCLogFileRotation=true NumberOfGCLogFiles=10 GCLogFileSize=10485760 PrintGCDetails=true PrintGCTimeStamps=true PrintGCDateStamps=true

以上是关于如何为 Apache Hadoop NameNodes 启用 GC 日志记录,同时防止日志文件覆盖和限制磁盘空间使用的主要内容,如果未能解决你的问题,请参考以下文章

如何为大数据处理构建高性能Hadoop集群

HDFS滚动升级

如何为 zeppelin 用户授予正确的权限

如何为hadoop实现组比较器?

如何为大型 MySQL 表轻松配置 Hadoop

如何为Hadoop集群选择正确的硬件