很多小伙伴在记录GC日志的时候都喜欢使用 UseGCLogFileRotation
这个参数,比如:
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/home/GCEASY/gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=20M
上面的例子中,JVM的一个日志文件达到了20M以后,就会写入另一个新的文件,最多会有5个日志文件,他们的名字分别是:gc.log.0、gc.log.1、gc.log.2、gc.log.3、gc.log.4
但是,这么做会有以下几个问题:
问题1:丢失旧的日志
如果你配置的日志文件个数是5个,一段时间过后就会产生出来5个日志文件,假如最老的是gc.log.0,最近的是gc.log.4,当gc.log.4到达20M以后,日志会重新写入到gc.log.0,gc.log.0之前的内容会被清空掉!
问题2:日志会变混乱
假如现在还是有5个日志文件:gc.log.0到gc.log.4,现在JVM重启了,此时GC的日志会重新从gc.log.0开始写入,但是gc.log.1、gc.log.2、gc.log.3、gc.log.4这里面的日志却还是之前旧的日志!新旧日志就掺杂在了一起!要解决这个问题,在重启服务器之前你需要把老的日志全部迁移到其他地方。
问题3:不方便日志集中管理
这种情况下,当前活动的日志文件的后缀名会被标记为.current
,假如当前活动的日志文件是gc.log.3
,那么他的文件名会被命名成gc.log.3.current
,如果你要把不同机器上的日志文件都放到一个集中的地方去的话,大多数运维人员都会使用rsyslog,但是这种命名方式对rsyslog来说是一个非常大的挑战!
问题4:对日志分析工具不友好
当使用日志分析工具(gceasy、GCViewer)来分析日志的时候需要上传多个日志文件而不是一个!
推荐的解决办法:
可以给GC日志的文件后缀加上时间戳,当JVM重启以后,会生成新的日志文件,新的日志也不会覆盖老的日志,只需要在日志文件名中添加%t的后缀即可:
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/home/GCEASY/gc-%t.log
或者更多参数
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCApplicationConcurrentTime
-XX:+PrintHeapAtGC
-Xloggc:/home/GCEASY/gc-%t.log
%t
会给文件名添加时间戳后缀,格式是YYYY-MM-DD_HH-MM-SS
。这样就非常简单了克服了UseGCLogFileRotation
存在的所有的问题!
原文:https://blog.gceasy.io/2019/01/29/try-to-avoid-xxusegclogfilerotation/