记一次线上频繁FGC的事件和解决方式

简介: 1.大量的请求,调用的地方要注意是否会导致内存的大量消耗,尽可能使用池化技术,单例等,减少创建,销毁的系统开销;2.CMS 的几个缺点,可以参考《深入java虚拟机》,对CPU占用会比较高,无法处理浮动垃圾,还有就是CMS使用的是标记-清除算法,会导致大量的空间碎片,碎片过多的话,导致分配大对象很困难,所以不得不进行FGC,也可能是这个原因导致了本文说的一直FGC的问题。

问题描述:

    早上去公司上班,突然就邮件一直报警,接口报异常,然后去查服务器的运行情况,发现java的cpu爆了.接着就开始排查问题

问题解决过程:

1.先服务器(centos7)上,使用了top和uptime命令,发现时java的cpu爆了,超过100%了,导致后续的服务无法正常提供;
2.调整了负载均衡,下掉了有问题的那几台机器;
3.使用jps找到了运行着的tomcat的pid,这里假设为10086;
4.使用jstat -gcutil 10086 500 10 (意思是对pid为10086的线程,每500ms显示各分代的内存使用情况), 这里给一下部分jvm的参数设置,如下:在这里插入图片描述
可以看到对新生代使用的是ParNew收集器,对老年代使用的是CMS收集器,CMSInitiatingOccupancyFraction=80说明当使用率超过80%的时候触发垃圾回收。然后发现,线上老年代一直超过80%的使用率,几乎一秒不到就进行了一次FGC,这么频繁的FGC导致了服务无法正常运行;
5.使用jmap -histo 查看了是哪些对象的数量最多,如果参数是-histo:live的话,会在进行一次FGC后,显示当前的使用数量最多的实例。查看后发现有大量的ConcurrentHashMap的Node节点实例,于是去代码中搜索使用到ConcurrentHashMap的地方,有好几处使用比较频繁的地方,看了代码后分析,可能是图片上传,下载的问题,但也不能断定。
6.使用jmap -dump:format=b,file=/usr/local/tomcat/dump1将内存的情况给拉下来.如下:在这里插入图片描述文件生成后,将dump1放入到eclipse的mat中进行分析。直接显示了一个疑似内存泄漏的问题。然后分析dump文件给出的信息,发现一个叫IdleConnectionReaper的类。dump文件里面说的内存泄漏的大概的意思就是说,IdleConnectionReaper这个类里面的ArrayList存放的东西太多了,爆掉了。如下:在这里插入图片描述
从oss的jar包里面找到这个类以后,简单的看一下这个类的构成,如下:
在这里插入图片描述
通过查找一些官方的资料和源代码的阅读,发现这个是一个oss的守护线程,用来检测上传或者下载的工作线程,每60秒就会去检查一下空闲的工作线程,并且将它们回收。然后它内部有一个静态的ArrayList,里面保存的是ossClient的链接,默认是1024个。
7.所以大概原因找到了,就是ossClient的链接太多了,扛不住了,所以一直在进行FGC,导致服务不可用了,最后找到相关的代码,发现有个小方法里面在每次上传或者下载的时候,都会去创建一个ossClient。修改了代码将ossClient调用的地方改成了单例。修改完线上跑了一段日子,后来也没有出现过这样的问题。

总结:

1.大量的请求,调用的地方要注意是否会导致内存的大量消耗,尽可能使用池化技术,单例等,减少创建,销毁的系统开销;
2.CMS 的几个缺点,可以参考《深入java虚拟机》,对CPU占用会比较高,无法处理浮动垃圾,还有就是CMS使用的是标记-清除算法,会导致大量的空间碎片,碎片过多的话,导致分配大对象很困难,所以不得不进行FGC,也可能是这个原因导致了本文说的一直FGC的问题。解决方式:
-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩(会整理内存碎片,默认是开启的).
-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩,会使得FGC的时间变长,但是可以提升内存空间的使用率,让大对象可以更容易分配,而不需要多次FGC。

相关文章
|
6月前
|
Oracle 数据库 UED
后台查询接口影响响应时间最大的因素:用空间换时间的优缺点及解决方案
1.当数据库的一个表记录很多显然查询数据很慢。 2.当数据库的一个表记录不大,但是数据很大也可能很慢。 我们的一个用户表中一个building很大,当查询100条数据就会把服务器的内存搞爆掉。 当然查询时要查询筛选有用字段,不可以直接把记录的所有字段都查拆来。这样能减少内存消耗和提高查询速度。 3.在经常查询字段上建立索引。据说oracle上用索查询和不用索引查询在超多记录的情况下相差1000倍。 4.若出现嵌套查询显然会大大增加相应查询时间。要先预处理用管道操作把能合并的查询合并到一个查询中,然后生成map,然后再处理。这是标准的用空间换时间的方案。
93 8
|
6月前
|
算法 Java
如何减少垃圾回收停顿时间,以提高高性能应用程序的响应性
如何减少垃圾回收停顿时间,以提高高性能应用程序的响应性
|
3月前
|
监控 负载均衡 算法
线程数突增!领导说再这么写就GC掉我:深入理解与优化策略
【8月更文挑战第29天】在软件开发的世界里,性能优化总是开发者们绕不开的话题。特别是当面对“线程数突增”这样的紧急情况时,更是考验着我们的技术功底和问题解决能力。今天,我们就来深入探讨这一话题,分享一些工作学习中积累的技术干货,帮助大家避免被“GC”(垃圾回收,也常用来幽默地表示“被炒鱿鱼”)的尴尬。
47 2
|
4月前
|
Java BI 运维
开发与运维配置问题之升级机器配置后出现频繁的GC问题和超长的GC时间如何解决
开发与运维配置问题之升级机器配置后出现频繁的GC问题和超长的GC时间如何解决
34 1
|
4月前
|
监控 Java 中间件
FGC频繁导致CPU 飙升定位及JVM配置优化总结
FGC频繁导致CPU 飙升定位及JVM配置优化总结
160 0
|
4月前
|
Java 运维
开发与运维内存问题之长期存活的对象最终会进入哪个内存区域如何解决
开发与运维内存问题之长期存活的对象最终会进入哪个内存区域如何解决
31 0
|
6月前
|
分布式计算 Java 数据库连接
回答粉丝疑问:Spark为什么调优需要降低过多小任务,降低单条记录的资源开销?
回答粉丝疑问:Spark为什么调优需要降低过多小任务,降低单条记录的资源开销?
60 1
|
5月前
|
Arthas 监控 Java
线上频繁fullgc问题-SpringActuator的坑
偷偷开启的监控在吃内存
111 0
|
6月前
|
监控 前端开发 Java
案例 2: 某寿险公司核心系统 GC 开销超限问题分析
案例 2: 某寿险公司核心系统 GC 开销超限问题分析
|
Java 调度
服务器常见问题排查(一)——cpu占用高、上下文频繁切换、频繁GC
文章主要讨论了服务器中常见性能问题的一些排查思路,这篇文章主要讨论了CPU负载过高,频繁GC和频繁切换上线文这三个问题。
1243 0
服务器常见问题排查(一)——cpu占用高、上下文频繁切换、频繁GC