ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

内存溢出+CPU占用过高:问题排查+解决方案+复盘(超详细分析教程)

2022-01-26 18:05:45  阅读:210  来源: 互联网

标签:dump 复盘 线程 内存 详细分析 CPU 溢出 日志


内存溢出+CPU占用过高:问题排查+解决方案+复盘(超详细分析教程)

原文地址

https://zhanghan.blog.csdn.net/article/details/109255980

 

前言

最近刚上线了一款社交项目,运行十多天后(运营持续每天推量),发现问题:

系统OOM(资源不能被释放)导致服务器频繁且长时间FGC导致服务器CPU持续飚高
日志中内存溢出:java.lang.OutOfMemoryError: Java heap space
程序十分卡顿,严重影响用户使用
从以下方面,为大家分享此次问题解决流程

问题出现现象
临时解决方案
复现问题
定位问题发生原因
优化代码
优化后进行压测,上线
复盘


学完本博文,你的收获


排查内存溢出的思路
排查内存溢出过程中用到的命令及工具(Linux命令,Eclipse Memory Anaylzer[MAT])
定位系统内存溢出的代码,并进行优化
此次内存溢出问题复盘


解决方案流程图

 

 

 

问题&临时解决方案&定位问题&最终解决方案

问题:

业务反馈程序用的十分卡,同时测试自己测的也十分卡

从ELK收集的请求日志发现确实存在问题,线上是两台部署:两台机器上都是,一次请求耗时由原来的几毫秒变为10几秒

CPU跑的过高,当时是4核,CPU持续飙到350%+;

当时一台服务器CPU截图:

 

 

 

临时解决方案

当时为了减少对业务影响,直接将生产两台服务器上的项目进行重启
项目启动参数中没有加内存溢出日志输出(后续博客为大家介绍JVM调优时讲解启动命令中加内存溢出日志输出),重启后出问题时项目的JVM信息丢失了
复现问题方式:在开发环境对程序进行持续压测;压测相关服务器配置:

服务器配置:8核,16G

项目启动内存:136M

Jmeter持续(循环)压发消息接口10分钟

定位问题

top命令查看最耗CPU的进程(进程:17038;CPU持续飙到595%+)

 

 

 top  -H  pid号,查看该进程中最耗CPU的线程(发现有一些线程占用CPU较高)

 

 

 将线程号转为16进制,同时查看这些线程当前正在干什么(在此以17045线程为例)

可以看到最耗CPU的线程都是在进行GC

注意:

在FGC的时候会引起STW,所有应用都会短暂暂停,但是此时CPU仍然很忙,因为CPU在忙着进行FGC清理内存

用Jmap命令查看当前堆的使用情况(发现老年代现在已占用99.8%+)

 

 

 查看gc 频率的命令(其中O代表老年代占用率,FGC是FullGC次数,FGCT是fullGC时间;可以看出在频繁FullGC但是老年代有资源一直释放不掉)

 

 

 通过分析出问题时线上日志发现内存溢出;至此定位到问题根源是内存溢出导致(有未释放资源堆积,导致老年代被占满,然后频繁的FullGC但是资源一直释放不了)

 

 

 分析问题产生原因

由于线上当时直接重启,未能保留当时的JVM内存文件;在开发环境进行循环压测,复现线上问题,然后导出dump文件进行分析找到原因

生成dump文件命令

 

 

 

 

 

 

 

 

 

分析代码

去代码中全局搜这两个类,发现只有在打日志的时候用到ClassClassPath类

分析ClassClassPath相关代码:

用到ClassClassPath对象是一个静态的ClassPool;

问题原因:classPath一直被静态的全局pool所持有,导致GC一直释放不掉;

 

 

 

 

 

 

 

 

 

 

 

 

优化代码:每次用完ClassClassPath后将其释放

每次对象使用完后从静态pool中移除
注意:classPath=null这种方式是不能释放掉的

 

优化后再次进行验证

开发环境循环压测,用MAT分析dump文件,发现内存中已不再堆积ClassClassPath类;优化前后接口吞吐量也提升8.2%
进行线上发布,观察一周后,对内存分析发现正常
复盘:

项目比对:
为快速开发,社交的代码从原来金融项目基础上改造而来;
原来金融项目没有内存溢出,而社交项目为什么内存溢出?
通过ELK统计一段时间的访问量结果:
社交目前日访问后台量65w+
金融项目只有4.5W+
社交和金融项目业务类型不一样,所呈现出的特点也不同
去生产的金融项目中dump内存文件,用MAT工具分析,发现也存在ClassClassPath类堆积释放不掉,只不过由于访问量少,堆积量未占满老年代而已;果断在金融项目迭代时将其优化;
程序预警:为减少业务影响,增加接口耗时的预警(后续博文为大家共享);实现方式:
- 在每次程序处理完进行预警(比如本次请求>阈值);缺点:消耗性能影响正常业务
- 在ELK清洗时用相关插件进行预警;优点:和业务解耦,对业务无影响

服务器预警:运维增加CPU内存,日志内存溢出监控

 

总结

解决内存溢出过程总结:

不同的项目导致内存溢出原因是不同的;

重要的是排查思路

经过不断的耐心的去观察,测试,分析才能定位到问题并最终解决问题

在这次分析内存溢出过程中,我们也针对我们项目的JVM启动参数进行了调优,在接下来的博文中为大家分享JVM调优

 

注意:

1,在FGC的时候会引起STW,所有应用都会短暂暂停,但是此时CPU仍然很忙,因为CPU在忙着进行FGC清理内存


2,使用jvisualvm来分析dump文件:
jvisualvm是JDK自带的Java性能分析工具,在JDK的bin目录下,文件名就叫jvisualvm.exe。
jvisualvm可以监控本地、远程的java进程,实时查看进程的cpu、堆、线程等参数,对java进程生成dump文件,并对dump文件进行分析。

 

原文地址

https://zhanghan.blog.csdn.net/article/details/109255980

 

标签:dump,复盘,线程,内存,详细分析,CPU,溢出,日志
来源: https://www.cnblogs.com/111testing/p/15847604.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有