JVM优化--优化gc

什么时候需要排查gc问题

我们遇到什么样的现象会怀疑gc有问题,进而优化呢?gc问题大体上可以分为两类:内存溢出、gc不健康。
内存溢出一般会借助dump文件进行查看,设置jvm参数-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/applogs/system/error.dump可以在发生oom时给出dump信息。有了dump信息可以使用MAT,Jprofile,jvisualvm 进行排查。
gc不健康主要表现在这么几个方面:young gc频繁或者不频繁,理想频率是5s一次,一次50ms以内。old gc理想频率是一天一次。这个参数根据应用的重要性、tps等会有不同的要求。例如我司的大多数RPC接口要求50ms以内响应,白天不允许发生full gc(发生full gc会stop the world,造成接口响应时间变长,容易引发短时间内大量接口超时。)
总结一下,当遇到OOM报错、服务有突刺、间歇性的超时等问题时,我们需要查看一下gc情况是否合理,即时调整。

gc不正常的原因

当发现gc情况跟我们上面说的指标不太一致时,可以尝试用这几个方面去分析原因。
young gc不正常原因一般是堆空间大小设置不合理,也有可能大对象直接进入老年代等。
old gc不正常可能原因有
1: Old 区内存不够;
2:元数据区内存不够;
3:System.gc();
4:jmap 或者 jcmd;
5:CMS Promotion failed 或者 concurrent mode failure;
6:JVM 基于悲观策略认为这次 YGC 后 Old 区无法容纳晋升的对象,因此取消 YGC,提前 FGC。

排查思路

1.分析gc问题,我们首先需要知道配置的jvm参数,jdk版本等信息。然后分析jvm参数的合理性,有初步的方向。
2.通过查看堆内存信息,了解堆内存的使用情况。
3.如果有监控工具,可以观察GC异常时间内,系统的调用情况。
4.结合GC日志进行排查。

实战演练

某应用最近进行重大升级,用户访问量扩大10倍,开发同事持续进行了两个月高强度的开发终于上线了。上线后总体平稳,但出现了两波超时。
当时没太当回事,超时发生在1分钟以内,且没有持续超时。以为是服务突刺、网络问题等导致的,没有跟踪。
第二天又发生了一次,这引起了我们的重视,想到可能有gc问题。
通过观察公司监控平台,发现对应时间点发生了full gc(如果公司缺少这样的监控平台,通过分析gc日志也能看出来,我们的垃圾回收器用的CMS+parnew,在gc日志里面搜索CMS可以看到full gc的情况,搜索GC (Allocation Failure))可以看到young gc的情况。young gc的情况一分钟15次左右,耗时比较短。
检查了一下JVM参数配置,指令是ps -ef|grep java 。由于我们的应用是部署在docker镜像上,一个镜像只部署了一个应用,这样找出来的就是我们的应用JVM配置。
观察到两个问题,没有设置元空间大小,老年代空间太小了,只有500M。
公司运维默认设置年轻代:老年代3:1,总共2G内存。调整为元空间默认256M,最大512M,年轻代1228M,老年代800M。
调整后重新部署效果很好,基本不会产生full gc,年轻代的GC情况也还正常。

你可能感兴趣的:(jvm)