JVM垃圾回收与一次线上内存泄露问题分析和解决过程

先说说事情的现象吧,本来运行好好的活动项目某一天突然服务报警(当时没有任何上线),客服陆续收到几个用户反馈投诉,查看日志发现有一台服务器各种报超时异常、cpu负载高,服务重启后一切正常,再过一天又是超时异常、cpu负载高。
乍一看现象还有点摸不着头脑,但有前面的内容聪明的你肯定猜到了什么原因,如果没有上述铺垫,我们根据该现象定位问题呢?
我们一般发现问题,都是从现象到本质,逐步递进的,如何从现象中提取有用信息加工并做判断很重要。

1.异常特征分析

特征一、 报错范围
:看到的是大量业务日志异常,大量操作超时和执行慢,redis超时、数据库执行超时、调用http接口超时

分析:首先排除是某一个db的问题
1.网络问题,ping服务器是通的,无丢包,查看wonder监控后台网络无丢包、网卡无故障 –排除网络问题
2.服务器cpu问题,top命令发现java应用cpu异常高,查看wonder监控后台也发现cpu负载高–这里并不是根本原因,只是现象

特征二、 报错普遍性
:查看其它服务器是否有相同异常,相同的代码,相同的jvm配置,只有一台服务器有问题,其它服务器正常

分析:跟这一台服务器代码或者系统设置有关系
1.操作系统设置导致  –这台服务器是虚拟机,跟其他虚拟机比较,参数配置一样,排除操作系统设置(当时上来先入为主,就认为是虚拟机配置不一样导致cpu过高,走了弯路)
2.负载均衡流量不均导致 –查看wonder监控后台流量无明显高,可以排除该原因
3.该机器运行与其它机器不一样的业务 –当时认为代码都一样的,忽略了定时任务

特征三 、持续性
:查看日志,开始报错后持续不断报错,cpu使用率持续高
分析:不是偶发状况

2.查看数据指标
ps: 这里简单说一下我们的业务监控后台,对诊断问题起很大的作用,可以看到cpu、线程、jvm内存等曲线图
使用的是springboot actuator报点 + prometheus收集 + grafana图形展示
springboot 只需要加上这两个包,加上一个配置就行了,零侵入,prometheus定时每10秒一次请求http接口收集数据,也不会对业务产生影响

1. 基于springboot的业务报点gradle配置:

compile 'org.springframework.boot:spring-boot-starter-actuator'

compile 'io.micrometer:micrometer-registry-prometheus'

yml配置文件加上:

management:

  endpoints:

      web:

        exposure:

          include: health,prometheus

          

默认报点的url:

http://ip:port/actuator/prometheus

2. 安装prometheus并配置对应的ip和收集的url

3. 安装grafana,并去grafana官网 dashboards中下载一个叫“Spring Boot 2.1 Statistics”的模板,导入就能看到漂亮的统计界面了
grafana监控后台
内存泄露-年轻代的eden区的特征: