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

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

我们最近决定在多个集群(具体版本各不相同)上为 Apache Storm worker 启用 GC 日志记录,以帮助调查与拓扑相关的内存和垃圾收集问题。我们想为工人做到这一点,但我们也想避免我们知道可能会发生的两个问题:

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

您可以通过 storm.yaml 中的 worker.childopts 属性 为 Storm worker 设置 JVM 选项(如果您通过 Apache Ambari 管理 Storm,请查看 Storm 服务 > 配置 > 高级风暴-站点 > worker.childopts)。您将向其添加额外的 JVM 属性。

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

您需要特别考虑日志文件名以防止覆盖。似乎您需要为每次调用取一个唯一的名称。为此,请利用 Storm code documentation 中提到的一些特殊的“%”字符串替换。对于唯一性,%WORKER-ID% 就足够了,它(很可能)对于每个工作进程都是唯一的。您可能还希望能够轻松判断 GC 日志的拓扑结构。在这种情况下添加 %TOPOLOGY-ID%(您可能需要说 %ID% 一些旧版本的 Storm);它可能很长,但会提供拓扑的名称。

到目前为止,JVM 选项是 -verbose:gc -Xloggc:/var/log/storm/storm-worker-%TOPOLOGY-ID%-%WORKER-ID%-gc.log-%TOPOLOGY-ID% 是可选的,路径应该与您的 Storm 日志目录匹配,并且您可以根据需要为日志文件命名)。

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

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

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

由于独特的文件命名,我们显然必须添加以避免覆盖,这意味着每个工作进程调用可以有 100MB,所以这不是管理风暴工作人员使用的磁盘 space 的完整解决方案子 GC 日志。对于每个进程,您最终会得到一组最多 10 个 GC 日志文件——这可以加起来。最好的解决方案(在 *nix 下)似乎是使用 logrotate 实用程序 定期清理最近N天未修改的worker GC日志。

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

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

总之,您将向 worker.childopts 添加如下内容:-verbose:gc -Xloggc:/var/log/storm/storm-worker-%TOPOLOGY-ID%-%WORKER-ID%-gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps 加上配置 logrotate。

最后,我应该提一下其他几个命名日志文件的选项,但我看不出有什么好处,至少对于我的用例而言:

  • 在某些版本的 Java 中,您可以将 %t 放在 GC 日志文件命名中,并且 Java 会将其替换为格式化为 <YYYY>-<MM>-<DD>_<HH>-<MM>-<SS> 的当前时间戳。也可以out %p 获取当前进程ID。
  • 有人告诉我,在某些情况下,您可以在 Storm 和 Java 的某些组合中放置反引号表达式,例如“date +'%Y%m%d%H%M'”,至少如果你使用安巴里。他报告说这适用于 Storm 0.10.0 和 Java 1.7.0_95,但我无法使用 storm 0.9.3.2.2.0.0-2041 和 java 1.7 获得该行为.0_75.