记一次内存溢出导致的生产事故

830 阅读3分钟

背景

因为同事的离职,半路被迫接手的一个可视化项目,使用ElasticSearch作为OLAP数据库、Docker作为部署工具等,突然有一天项目现场环境出现JVM内存溢出问题,被迫披挂上阵定位问题的原因

分析过程

top命令查看系统资源占有情况,cpu占用不高,内存占用高,并且虚拟内存高达16g

https://i.loli.net/2020/12/19/W6NDft3gj9Ces1d.png

Tips:Java 程序由于自己维护堆的使用,导致调用 glibc 去管理内存的次数较少。更糟的是 Java 8 开始使用 metaspace 原空间取代永久代,而元空间是存放在操作系统本地内存中,那线程一多,每个线程都要使用一点元空间,每个线程都分配一个arena,每个都64MB,就会导致巨大的虚拟地址被分配。

free -h 查看内存占有,buffer/cache占有很大,总内存剩余7g

https://i.loli.net/2020/12/19/l6NOYTWryM3Hm12.png

Tips:buffers是用来缓冲块设备做的,它只记录文件系统的元数据(metadata)以及 tracking in-flight pages,而cached是用来给文件做缓冲。更通俗一点说:buffers主要用来存放目录里面有什么内容,文件的属性以及权限等等。而cached直接用来记忆我们打开过的文件和程序。

通过系统日志中的java.lang.OutOfMemoryError与系统资源占用情况基本定位是jvm内存溢出造成的

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/77d3f825f62f4f81bca3c0c631f92a3c~tplv-k3u1fbpfcp-zoom-1.image

进一步使用jdk自带性能监控工具查找原因

  • jmap -heap 1 //查看堆内存情况,无此命令参数,因为该服务使用的是docker镜像的openjdk导致缺失部分jdk完整工具支持

    https://i.loli.net/2020/12/20/4xTZCLFfbMd5VGX.png

  • jstat -gc 1 250 10 //查看垃圾回收gc状态情况,新生代与老年代内存基本耗尽,FullGC高达1200多次,但是未释放成功

    https://i.loli.net/2020/12/20/QAt27KdJsok6vOS.png

  • jmap -histo:live 1  | head -n 100 //查看top前100的实例数量情况,再次受阻,报错Unable to get pid

    https://i.loli.net/2020/12/20/Qi5DdSaogpKbwPn.png

执行jmap命令遇到的Unable to get pid可以采用的解决方案:

  • 在docker run时加上 --init 参数
  • 安装Tini,使用tini作为入口进程,配置启动java进程

接下来,我们使用Alibaba开源的诊断工具Arthas可视化工具排查问题(PS:如果大家对Arthas不了解,可以查看官方文档)

下载arthas全量jar>拷贝到容器内>成功启动jar

docker cp 解压绝对路径 platform:/tmp/

docker exec -it  platform /bin/sh -c "cd /tmp/arthas; java -jar arthas-boot.jar"

https://i.loli.net/2020/12/20/b4dxnaDTUImozY6.png

执行dashboard查看资源占有情况

https://i.loli.net/2020/12/20/HKkWr7qdoni2gPQ.png

通过dashboard了解到资源已基本耗尽,线程执行基本正常,最终需要通过导出dump文件分析内存分布进行分析

执行heapdump /tmp/dump.hprof导出dump文件,下载dump文件到本地,通过MAT工具进行分析

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dcd0cbc3434244c19803de44fd8dd638~tplv-k3u1fbpfcp-zoom-1.image

最终定位问题是因为项目中未正确使用缓存导致的

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/afde30871d194b88b620c1582f947083~tplv-k3u1fbpfcp-zoom-1.image

参考

mac下安装MAT进行分析

链接:blog.csdn.net/hanchao5272…

openjdk-alpine容器中的jvm如何执行dump

链接:www.crazy1984.com/2018/12/dev…