如何为 Apache Kafka 代理启用 GC 日志记录,同时防止日志文件覆盖和限制磁盘 space 使用

How to enable GC logging for Apache Kafka brokers, while preventing log file overwrites and capping disk space usage

我们最近决定在多个集群(具体版本各不相同)上为 Apache Kafka 代理启用 GC 日志记录,以帮助调查与 Kafka 相关的内存和垃圾收集问题。我们想为 运行 broker 这样做(而不是为 "kafka-topics.sh" 等 Kafka 操作)。我们还想避免两个我们知道可能会发生的问题:

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

在运行kafka-server-start.sh之前设置环境变量GC_LOG_ENABLED为"true",启用GC logging,但并没有解决上述两个问题。这会添加这些固定的参数集:-Xloggc:<gc-log-file-loc> -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps 其中 gc-log-file-loc 与使用“-gc.log”而不是“.out”的 .out 文件位于同一目录和名称中。

您可以在 运行ning kafka-server-start.sh 之前使用下面的特定 JVM 参数设置 KAFKA_GC_LOG_OPTS。这是有效的,因为 kafka-运行-class.sh 在 JVM 选项中特别包含该环境变量的内容,但前提是它在其命令行上传递 -loggc ; kafka-server-start.sh 确实通过了这个。

如果您通过 Apache Ambari 启动 Kafka,您可以在 Kafka 服务 > 配置 > 高级 kafka-env > kafka-env 模板中设置 KAFKA_GC_LOG_OPTS。如果你在这里设置它,它似乎只会用于kafka-server-start.sh。其他脚本目前没有将 -loggc 传递给 kafka-运行-class.sh.

现在让我们讨论要包含在 KAFKA_GC_LOG_OPTS 中的 JVM 参数。

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

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

的代理启动时间戳替换。

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

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

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

由于独特的文件命名,我们显然必须避免覆盖,您可以有 1000MB 每个代理进程调用,所以这不是管理磁盘的完整解决方案space 被 Kafka broker GC 日志使用。对于每个代理,您最终会得到一组最多 10 个 GC 日志文件——这可能会随着时间的推移而增加。最好的解决方案(在 *nix 下)似乎是使用 logrotate 实用程序(或其他一些实用程序)定期清理最近 N 天内未修改的代理 GC 日志。

一定要算一下,确保你有足够的磁盘 space。

人们经常希望在他们的 GC 日志中看到比默认情况下更多的详细信息和上下文,因此请考虑添加 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps,就像在 GC_LOG_ENABLED=true 中所做的那样。

Putting all end parameters together into KAFKA_GC_LOG_OPTS and starting a broker you might have:
TIMESTAMP=`date +'%Y%m%d%H%M'`
# GC log location/name prior to .n addition by log rotation
GC_LOG_NAME="{{kafka_log_dir}}/kafka-broker-gc.log-$TIMESTAMP"

GC_LOG_ENABLE_OPTS="-verbose:gc -Xloggc:$GC_LOG_NAME"
GC_LOG_ROTATION_OPTS="-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
GC_LOG_FORMAT_OPTS="-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps"

export KAFKA_GC_LOG_OPTS="$GC_LOG_ENABLE_OPTS $GC_LOG_ROTATION_OPTS $GC_LOG_FORMAT_OPTS"
./kafka-server-start.sh server.properties

在命令行中,将 {{kafka_log_dir}} 替换为您的 Kafka 日志目录的位置或 GC 日志所在的任何位置。您也可以更改日志文件命名。

在 Ambari 下,您可以将这些行(但不是 运行ning kafka-server-start.sh)添加到 Ambari UI 中的 "kafka-env template" 字段。 {{kafka_log_dir}} 将自动替换为在字段上方不久定义的 Kafka 日志目录。您需要重新启动代理以启动代理日志记录(考虑进行滚动升级)。