一.前置环境

1. 运行在k8s集群上的Pod服务(Java程序)

2. MAT分析工具(Eclipse Memory Analyzer)

二.利用Jmap工具导出Heap Dump

1.执行命令进入pod容器

kubectl exec -itn {namespace} {pod} sh

2.利用jmap生成java程序的Dump文件

jps | grep {jar}
./jmap -dump:live,format=b,file=haep.hprof 8

3.利用k8s命令导出Dump文件到本地

kubectl cp -n {namespace} {pod}:/usr/lib/jvm/java-1.8-openjdk/bin/haep.hprof haep.hprof

4.导入MAT分析工具

三.利用MAT工具分析可疑内存泄漏

1.基本原则

     千万不要等到OOM发生才去采取行动,尽最大可能性保证上线后的服务不会发生OOM错误。

2.预先分析

      当我们完成业务开发后,需要对业务运行情况进行相应的测试,保证程序不会发生OOM错误,以下提供二种思路:

      (1)针对大对象的性质考虑

      (2)针对时间序列上的可疑增长考虑

       当我们将Dump文件导入MAT分析工具时,可以根据上诉两种思路判断可能导致OOM错误的原因。

  3. 针对大对象的性质考虑

  

当导入Dump文件时,会有一个饼图,可以看出当前进程的占用内存最多的对象,一般而言,我们可以集中分析Top-N 的对象,分析各个大对象内存占用是否合理,进而判断各个对象是否有可能造成内存溢出。

  4. 针对时间序列上的可疑增长考虑

     一次Dump操作很难判断出当前程序是否存在内存泄漏,是否会导致内存溢出。基于此,需要我们在系统运行后每隔一定时间T进行Dump操作。     

      假设存在时间tn上对应的Dump文件f(tn),通过对比不同时间序列上的对象实例数量,对稳定运行一段时间依旧不断增长对象的类进行专门分析,通过提前解决过滤内存溢出问题达到不发生OOM的期望。

     以上描述可操作于:

    1.点击其中一个Dump文件下

操作:Actions -> Histogram 

  2.选择按照class进行分组查看数据

操作:Group by class 

 

3. 和其余时间段Dump文件进行对比

操作:Compare to another heap dump

如上图,+0表示两个dump文件对象数量无增长。此处仅为举例,实例情况下对象一般都有增长和减少。基于此,应该重点分析数值变化比较大的对象

4.MAT工具提供了许多实用功能,笔者也在学习,本文不在介绍其余详细使用。

5.补充,若事先确实无法避免OOM,那么请加上相关JVM参数,当程序发生OOM时,JVM会自动dump下当前进程情况。事后拿到dump文件,便可以通过各种MAT进行分析啦。

-XX:+HeapDumpOnOutOfMemoryError

四.总结

    OOM真正解决的时期不应该是到了生产环境,而是应该提前发现并解决,甚至在编码前预先判断业务使用资源情况,编码时灵活运用设计模式等方法来避免。这是一个可以避免的错误类型

  

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐