如何为 Apache Hadoop NameNode 启用 GC 日志记录,同时防止日志文件覆盖和限制磁盘 space 使用
How to enable GC logging for Apache Hadoop NameNodes, while preventing log file overwrites and capping disk space usage
我们最近决定在多个集群(具体版本各不相同)上为 Hadoop NameNode 启用 GC 日志记录,以帮助调查与 NameNode 相关的内存和垃圾收集问题。我们希望集群中的所有 NameNode(活动和备用或主要和次要)都这样做。我们还想避免两个我们知道可能会发生的问题:
- NameNode 因任何原因重启时覆盖日志文件
- 日志使用过多磁盘 space,导致磁盘被填满
当 Java GC 日志记录开始时,它似乎会替换任何同名文件的内容。这意味着除非您小心,否则您将丢失 GC 日志记录,也许在您更有可能需要它的时候。
如果您将集群 运行 保持足够长的时间,除非进行管理,否则日志文件将填满磁盘。即使 GC 日志记录目前不是很多,我们也希望管理出现导致日志记录率飙升的异常情况的风险。
可以在 hadoop-env.sh 中设置环境变量的几个选项,以便在启动时为 NameNode 传递 JVM 参数:
HADOOP_OPTS
(适用于所有已启动的客户端和服务器调用
"hadoop",甚至 "hadoop dfs")
HADOOP_NAMENODE_OPTS
(使用 NameNode HA 这会影响活动和备用 NameNode,而没有 NameNode HA 会影响主 NameNode)
HADOOP_SECONDARYNAMENODE_OPTS
(影响secondary NameNode,如果没有NameNode HA)
这个问题专门针对 NameNode,因此我们希望将 JVM 参数添加到 HADOOP_NAMENODE_OPTS
和 HADOOP_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 启动时间戳替换。
现在开始管理磁盘的使用 space。如果有比我现有的更简单的方法,我会很高兴。
首先,利用 Java 的内置 GC 日志文件轮换。 -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M
是一个启用这种循环的例子,有多达 10 个来自 JVM 的 GC 日志文件,每个文件的大小不超过 10MB。 10 x 10MB 是 100MB 最大使用量。
随着 GC 日志文件轮换最多 10 个文件,“.0”、“.1”...“.9”将添加到您在 [=18= 中提供的文件名中]. .0 将是第一个,在达到 .9 后它将替换 .0 并以循环方式继续。在某些版本中 Java '.current' 将被附加在当前正在写入的日志文件名称的末尾。
由于独特的文件命名,我们显然必须避免覆盖,您可以有 100MB 每个 NameNode 进程调用,所以这不是管理磁盘的完整解决方案space 被 NameNode GC 日志使用。您最终将在每个 NameNode 服务器上得到一组最多 10 个 GC 日志文件——这可能会随着时间的推移而增加。最好的解决方案(在 *nix 下)似乎是使用 logrotate 实用程序(或其他一些实用程序)定期清理最近 N 天未修改的 NameNode GC 日志。
一定要算一下,确保你有足够的磁盘 space。
人们经常希望在他们的 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_OPTS
和 HADOOP_SECONDARYNAMENODE_OPTS
的上方某处。然后将 $HADOOP_NAMENODE_OPTS
添加到 HADOOP_NAMENODE_OPTS
和 HADOOP_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 都在线,那么您可以一次重启一个而无需停机。
我们最近决定在多个集群(具体版本各不相同)上为 Hadoop NameNode 启用 GC 日志记录,以帮助调查与 NameNode 相关的内存和垃圾收集问题。我们希望集群中的所有 NameNode(活动和备用或主要和次要)都这样做。我们还想避免两个我们知道可能会发生的问题:
- NameNode 因任何原因重启时覆盖日志文件
- 日志使用过多磁盘 space,导致磁盘被填满
当 Java GC 日志记录开始时,它似乎会替换任何同名文件的内容。这意味着除非您小心,否则您将丢失 GC 日志记录,也许在您更有可能需要它的时候。
如果您将集群 运行 保持足够长的时间,除非进行管理,否则日志文件将填满磁盘。即使 GC 日志记录目前不是很多,我们也希望管理出现导致日志记录率飙升的异常情况的风险。
可以在 hadoop-env.sh 中设置环境变量的几个选项,以便在启动时为 NameNode 传递 JVM 参数:
HADOOP_OPTS
(适用于所有已启动的客户端和服务器调用 "hadoop",甚至 "hadoop dfs")HADOOP_NAMENODE_OPTS
(使用 NameNode HA 这会影响活动和备用 NameNode,而没有 NameNode HA 会影响主 NameNode)HADOOP_SECONDARYNAMENODE_OPTS
(影响secondary NameNode,如果没有NameNode HA)
这个问题专门针对 NameNode,因此我们希望将 JVM 参数添加到 HADOOP_NAMENODE_OPTS
和 HADOOP_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 启动时间戳替换。现在开始管理磁盘的使用 space。如果有比我现有的更简单的方法,我会很高兴。
首先,利用 Java 的内置 GC 日志文件轮换。 -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M
是一个启用这种循环的例子,有多达 10 个来自 JVM 的 GC 日志文件,每个文件的大小不超过 10MB。 10 x 10MB 是 100MB 最大使用量。
随着 GC 日志文件轮换最多 10 个文件,“.0”、“.1”...“.9”将添加到您在 [=18= 中提供的文件名中]. .0 将是第一个,在达到 .9 后它将替换 .0 并以循环方式继续。在某些版本中 Java '.current' 将被附加在当前正在写入的日志文件名称的末尾。
由于独特的文件命名,我们显然必须避免覆盖,您可以有 100MB 每个 NameNode 进程调用,所以这不是管理磁盘的完整解决方案space 被 NameNode GC 日志使用。您最终将在每个 NameNode 服务器上得到一组最多 10 个 GC 日志文件——这可能会随着时间的推移而增加。最好的解决方案(在 *nix 下)似乎是使用 logrotate 实用程序(或其他一些实用程序)定期清理最近 N 天未修改的 NameNode GC 日志。
一定要算一下,确保你有足够的磁盘 space。
人们经常希望在他们的 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_OPTS
和 HADOOP_SECONDARYNAMENODE_OPTS
的上方某处。然后将 $HADOOP_NAMENODE_OPTS
添加到 HADOOP_NAMENODE_OPTS
和 HADOOP_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 都在线,那么您可以一次重启一个而无需停机。