一、背景介绍:
运行在k8s集群中负责支付业务一个服务,运营一段时间就会被k8s kill,然后重启, 通过查看k8s 的event发现系统达到了memory到达了上限被集群kill调。
服务配置:jdk:1.8、堆内存:-Xmx800m -Xms800m 设置为800M, k8s的memory.limit设置为1G。
二、排查问题:
1.初步分析: 由于系统的请求量不大,所以设置的堆内存足够了,所以可以排除堆内存设置过小原因。同时由于服务被kill的原因是因为物理内存占用过大。所以怀疑是堆外内存溢出。
jvm内存结构分为:堆内存(新生代、老年代), 堆外内存(线程栈、元空间、直接内存)
2.排查:
2.1 gc状态分析:jstat -gcutil pid 5s
结果:各区域的占用情况,gc情况无明显异常
2.2 堆dump: jmap -dump:format=b,file=heap.hprof pid, 使用mat分析如下:
很明显 com.mysql.jdbc.NonRegisteringDriver占用堆内存的33%。其中java.util.concurrent.ConcurrentHashMap$Node[] 存在内存泄漏的可能。
ConcurrentHashMap connectionPhantomRefs 保存mysql co