有个生产环境CRM业务应用服务,情况有些奇怪,监控数据显示内存异常。内存使用率99.%多。通过生产监控看板发现,CRM内存超配或内存泄漏的现象,下面分析一下这个问题过程记录。
1、服务器硬件配置部署情况
生产服务器采用阿里云ECS机器,配置是2HZ、8GB,单个应用服务独占,CRM应用独立部署,即单台服务器仅部署一个java应用服务。
用了6个节点6台机器,每台机器都差不多情况。
监控看板如下:
top命令查看物理占用情况
通过看板情况来看确实存在异常情况,下面进一步分析问题原因。
2、应用启动参数配置
应用启动配置参数如下:
/usr/bin/java
-javaagent:/home/agent/skywalking-agent.jar
-Dskywalking.agent.service_name=xx-crm
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp/xx-crm.hprof
-Dspring.profiles.active=prod
-server -Xms4884m -Xmx4884m -Xmn3584m
-XX:MetaspaceSize=512m
-XX:MaxMetaspaceSize=512m
-XX:CompressedClassSpaceSize=128m
-jar /home/xxs-crm.jar
堆内:最大最小堆内存4884m约4.8G左右,其中新生代-Xmn3584m 约3.5G左右,
非堆: 元数据区配置 512M,类压缩空间 128M, Code Cache、buffer等代码缓存区240M(没有配置参数,通过监控看板看到的)。
3、内存分布统计
从监控看板的数据来看,我们简单统计一下内存分配数据情况。
通过JVM配置参数和监控看板数据可知:
堆内存:4.8G
非堆内存:(Metaspace)512M+(CompressedClassSpace)128M+(Code Cache、Buffer等)240M约等1GB左右。
堆内存(heap)+非堆内存(nonHeap)=5.8G
8GB物理内存除去操作系统本身占用大概占500M。即除了操作系统本身占用之外,还有7.5G可用内存。
但是 7.5-5.8=1.7GB,起码至少还有1~2GB空闲才合理呀!怎么内存占用率99%多,就意味着有1~2G不知道谁占去了,有点诡异!
4、问题分析
先看一下JVM内存模型,环境是使用JDK8
JVM内存数据分区如下图所示:
堆heap分配结构如下图所示:
堆大家都比较熟悉,也容易理解的,也是java程序接触得最多的一块,不存在什么数据上统计错误,或占用不算之类的。
那说明额外占用也非堆里面,只不过没有统计到非堆里面去,曾经一度怀疑监控prometheus展示的数据有误。
其实不是监控统计的问题,那是什么问题呢?
先看一下dump文件数据,这里使用MAT工具(一个开源免费的内存分析工具,个人认为比较好用,推荐大家使用。下载地址:https://www.eclipse.org/mat/downloads.php)。
通过下载内存dump镜像观察到,如下图所示:
有个offHeapStore,这个东西堆外内存,可以初步判断是 ehcahe引起的。
<