记录一次生产jvm问题的排查

记录一次生产问题的排查

第一天晚上

现象

1、前援反馈页面有接口陆续出现请求超时

2、登录后台服务器top命令查看发现java进程发生高cpu占用情况

3、查看对应业务日志,报数据库连接等待超时-数据库连接池连接无空闲
对应处理

1、临时调大数据库连接池最大连接数限制,从20调整到50

2、重启服务,先保证业务可用

第二天

观察服务器指标

1、free -h 查看内存使用情况,java进程占用高内存

2、查看进程gc情况,jstat -gc 2773947 1000 10,因为该项目没有打印GC日志只能这样临时观察。查看GC日志,

依次是

S0C:幸存0区容量(约350M)、

S1C:幸存1区容量(约350M)、

S0U:幸存0区已使用(201M)、

S1U:幸存1区已使用(0M因为是年轻代用-XX:+UseParNewGC,复制算法)

新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区。一个Eden区,两个 Survivor区(一般而言)。大部分对象在Eden区中生成。回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复

EC:伊甸区容量350M

EU:伊甸区已使用97M

OC:老年代容量4194M

OU:老年代已使用2878M

MC:元空间大小213M,jdk1.8之前叫永久代

MU:元空间已使用196M

CCSC:压缩类空间大小;(暂不知道用处)

CCSU:压缩类空间使用大小;(暂不知道用处)

YGC:年轻代gc 4786

FGC:老年代GC(可以看下图,这是两次GC日志的对比,才短短几分钟就出现了两次Full GC,而且查看上下两次GC情况,发现在FULL GC后垃圾有被回收,即EU和OU有变小,先排除内存泄漏。可以猜测应该是有大对象产生触发老年代空间担保机制,直接将老年代占满从而触发FULL GC。)

3、通过jmap -histo 18830| head -n 20 命令查看堆中比较多的对象

根据PaTerminalRealTimeQuery对象找到近期提交的代码,是漏掉一个设备id的参数,导致数据库中200w的设备数据都被捞到list中来。产生了大对象。

总结:主要是大对象的产生导致第一天的数据库连接被占用,第二天的内存过大、频繁FULL GC问题。

优化范式:

1、调整错误的业务代码

2、增加gc日志及dump文件的打印,具体参数改变如下
修改前:

-Xms5120M -Xmx5120M -Xmn1024M -XX:PermSize=256M -XX:MaxPermSize=512M -Xss256K -XX:SurvivorRatio=1 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:SoftRefLRUPolicyMSPerMB=0

修改后:

-Xms3072M -Xmx3072M -Xmn1024M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M -Xss256K -XX:SurvivorRatio=1 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -verbose:gc -Xloggc:/tysl/log/gc/manageLoadBalance-gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tysl/log/

修改点:

1、内存用不了这么大,反而老年代过大反而会让stw的时间边长,调小老年代内存

2、增加gc日志及dump的打印信息,以便后续排查问题

3、原项目估计是从1.7升级到1.8的,永久代的参数没有改过来,极端情况下,如遇到某些动态代理对象的生成会将元空间不断扩展(因为元空间不设置默认是共享整个物理内存空间的,极端场景会压缩堆空间,触发频繁FULL GC)-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M

相关推荐
程序员弘羽5 小时前
C++ 第四阶段 内存管理 - 第二节:避免内存泄漏的技巧
java·jvm·c++
好名字更能让你们记住我7 小时前
Linux多线程(十二)之【生产者消费者模型】
linux·运维·服务器·jvm·windows·centos
心平愈三千疾16 小时前
通俗理解JVM细节-面试篇
java·jvm·数据库·面试
我不会写代码njdjnssj16 小时前
网络编程 TCP UDP
java·开发语言·jvm
第1缕阳光16 小时前
Java垃圾回收机制和三色标记算法
java·jvm
亲爱的非洲野猪10 天前
一次性理解Java垃圾回收--简单直接方便面试时使用
java·jvm·面试
Ray_199710 天前
C++二级指针的用法指向指针的指针(多级间接寻址)
开发语言·jvm·c++
转码的小石10 天前
Java面试复习指南:并发编程、JVM、Spring框架、数据结构与算法、Java 8新特性
java·jvm·数据结构·spring·面试·并发编程·java 8
转码的小石10 天前
Java面试复习:Java基础、面向对象编程、JVM原理、Spring框架解析
java·jvm·spring·面试·java基础·面向对象·复习
MuYiLuck10 天前
【JVM|内存结构】第一天
jvm