用户在 14:32 反馈接口卡了十秒,监控上只有一条 CPU 从 30% 冲到 95% 的尖刺,jstat 是事后才接的,GC 记录一条都没有。碰到这种情况,我一般先确认改动有没有真的生效。
原因不复杂,启动脚本沿用了老模板,没有加 GC 日志参数,JVM 默认不输出。事后只能靠 CPU 曲线猜,无法区分是 GC 停顿还是线程死锁。
「GC 日志未开启」这类改动最怕改一半,回滚脚本先准备好,再动生产。改完顺手把文档补一句,省得下次自己重新推一遍。
java -Xlog:gc*:file=/var/log/app/gc.log:time,uptime,level,tags:filecount=5,filesize=50m \ -jar app.jar jcmd 21455 VM.flags | tr ' ' '\n' | grep -i gc
监控和日志的时间要对上,时区不一致会多绕很大一圈。临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。
动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。
具体做法是,立刻在启动参数补 -Xlog:gc*:file 带时间戳和 uptime;用 jcmd GC.heap_info 和 VM.flags 先记录当前状态;下一次卡顿前保持日志开着 用 logrotate 控制大小;对照 GC 日志里的 pause 时间和接口超时时间点。
最后用这个标准收尾,下一次卡顿时 gc.log 里有对应时间点的 pause 记录 能读出停顿类型和时长。
