Java Flight Recorder - 持续滚动记录

7

问题

如何实现一个带有最大年龄限制的滚动记录并将其保存到磁盘中?

背景

当服务器出现故障时,我想能够倾泻出之前几个小时的分析信息,并进行分析,以了解出了什么问题。

  1. 由于我不知道何时会发生故障,因此JDK应该持续将事件保存到磁盘上。
  2. 由于服务器不经常重新启动,为避免文件无限增长,我需要设置某种容量限制(可以是按年龄或大小)。

因此,换句话说,我想让JDK将记录连续保存到磁盘中,但删除旧的文件/记录,使总量保持在某个阈值以下(按年龄或大小)。

为此,以下是版本Oracle JDK 1.8.0_144提供的选项:

-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder
-XX:StartFlightRecording
   name=<foo-bar>
-XX:FlightRecorderOptions
   defaultrecording=true   // what does this do even?
   disk=true
   maxage=1h // this is what I thought would solve my problem! 
   repository=<path-to-where-I-want-the-recording>
   maxchunksize=5M

我本以为设置maxage=1h只会在磁盘上保留最近1小时的记录,但不是这样!现在已经过去了1天,文件仍没有被限制。

同时,maxchunksize似乎起作用了。各种.jfr文件大约有5M。由于年龄限制没有得到执行,因此有很多这样的文件。

我做错了什么?


为什么不创建一个定时任务来删除旧文件呢? - Kayaman
5
@Kayaman 提出解决方法并不能很好地解决根本原因。 - GhostCat
问这样的问题包括“// 这到底是干什么的?”并不能充分展现我的客户支持技能。 - Kayaman
3
@Kayaman cron作业增加了系统的复杂性。这是一个额外需要记住、维护和记录的事情,导致系统变得脆弱。此外,这是一个简单的行为,人们会认为大多数JFR用户都期望并实际上需要它,因此“本地”解决方案很可能已经存在。 - cmhteixeira
3
  1. 这就是我在这里发布的原因。
  2. 没必要无礼。我的问题清晰、简洁、经过精心策划。你的挫败感是没有根据的。
  3. 我没有找到关于 defaultrecording 含义的文档。你有吗?
- cmhteixeira
2个回答

4

我认为问题在于您开始了两个录制,一个使用-XX:StartFlightRecording,另一个使用-XX:FlightRecorderOptions=defaultrecording=true

使用-XX:StartFlightRecording的录制是无界的。我认为对于Oracle JDK 1.8.0_144和您的用例,以下选项将是适当的:

-XX:+UnlockCommercialFeatures
-XX:FlightRecorderOptions=repository=<path>
-XX:StartFlightRecording=maxage=1h,name=<name>

-XX:+UnlockCommercialFeatures是必需的,因为JFR是Oracle JDK 8中的商业功能。从JDK 11开始,不再需要。

-XX:+FlightRecorder对于JDK 8u40或更高版本,与-XX:StartFlightRecoding无关。JFR缓冲区现在是在启动第一个记录时设置的,而不是在JVM启动时设置的。如果使用defaultrecording=true启动记录,则仍然需要-XX:+FlightRecorder

-XX:FlightRecorderOptions=defaultrecording=true做了很多事情,主要是出于历史原因,但仅在进行内存记录时需要。从JDK 9开始,该选项不再需要并已被删除。

如果使用推荐的方法启动JFR -XX:StartFlightRecording,则不需要-XX:FlightRecorderOptions=disk=true,maxage=1h

除非出现问题,否则应将maxchunksize保留为默认值(12 MB)。JFR已经针对此大小进行了优化和测试。


3

我接受 Kire Haglin 的答案。

为了让这个JDK对我更加有效,我再增加一些价值。

-XX:+UnlockCommercialFeatures
-XX:StartFlightRecording
  name=<foo-bar>
  maxage=12h
  dumponexit=true
-XX:FlightRecorderOptions
  dumponexitpath=<path-to-file>.jfr
  disk=true
  repository=<some-folder-path>

请注意我原始问题中没有的额外参数dumponexitdumponexitpath。最终我还需要这些参数。
经过试错,似乎必须将dumponexit存在于XX:StartFlightRecording参数中,而dumponexitpath存在于FlightRecorderOptions参数中。其他任何排列似乎都不起作用。

同时请注意,删除-XX:+FlightRecorderdefaultrecording=true(如Kire所建议的)仍然有效。话虽如此,我认为defaultrecording=true的存在并没有触发双重记录。
我这么说是因为当执行命令jcmd <PID> JFR.check <name>时,我只得到了一个条目。


你尝试过不加<name>的 "jcmd <PID> JFR.check" 吗? 如果你想要一个固定的文件名(而不是自动生成的),你应该可以使用-XX:StartFlightRecording=filename=dump.jfr,dumponexit=true,maxage=1h,然后只需要 -XX:FlightRecorderOptions=repository=<some-folder-path>。 如果你想要自动生成文件名,则不能使用 -XX:StartFlightRecording,并且需要使用默认的defaultrecording=true路径和dumponexitpath。 所有这些问题在JDK 9中得到了修复。 - Kire Haglin
关于没有 <name> 的命令,这是一个很好的观点。我已经不记得了。如果我确实使用了名称来发出它,也许我确实触发了两个记录。谢谢你提供的其他信息。真是一团糟啊。xD - cmhteixeira

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接