当前位置:   article > 正文

pod内存达到上限,重启了

pod内存达到上限,重启了

背景:

深夜告警,内存超过limit导致pod重启,清晨到公司查看JVM和pod的监控,返现内存占用很多。

遇到的问题:
1、为什么没有报OOM异常,pod直接重启了?
2、为什么使用过的内存没有及时回收?
3、为什么jvm堆空间回收后占用很少内存,而pod的内存占用率仍然很高?

处理过程:
安装jvm的分析工具和arthas,参考我的;另一篇blog:
https://blog.csdn.net/l12127556/article/details/138632103?spm=1001.2014.3001.5502

1、首先到ES里查询业务日志,根据重启时间查询前后十分钟甚至更长时间业务日志,观察业务量是否大量增加(凌晨,一般不存在),是否大任务(查询数据量特别多的任务或者处理时间特别长的任务)存在。
2、通过业务日志可以发现,pod重启前后,业务请求没有出现激增,也就是qps没有多少,但是却有一个定时任务触发了查询全部数据的逻辑,数据在从数据库中查询之后,在内存中进行了较为复杂的逻辑计算,在计算过程中难免进行了多次复制,有可能是这个逻辑导致jvm使用量激增,最终导致pod重启。
3、于是在测试环境创建了相同的数据量进行重现,通过分析jvm各部分的使用情况,发现堆空间没有及时释放,通过jmap命令查询占用内存最多的对象,发现是一个entity类的对象,这肯定是不正常的,因为在查询结束后,应该就被释放掉了。
4、对jvm强制GC,可以发现堆中的大部分对象都被回收了,但是pod的内存占用率仍然很高。
5、看了文档发现,有些垃圾回收器的内存是没办法交还给系统的,即不能被pod回收。(条件有限,没有做验证实验)

因为涉及真实项目,所以以上分析和定位问题的过程没有贴图,略显枯燥。

文中用到的命令:

#打印对空间里的对象统计信息
jmap -histo <pid> > obj.log
#强制GC
jcmd <pid> GC.run

#arthas强制GC
vmtool --action forceGc
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

问题回答:
java 启动的参数设置: -Xms2048m 和 -Xmx2048m
pod的limit设置:2048m

1、因为pod的limit是2048m,而jvm的Xmx设置了2048,由于jvm的堆内存还没有使用完时,已经达到了pod的limit,所以没有报OOM,而是pod直接重启了。
2、由于pod在启动时还要占用一部分内存,所以jvm真正使用的内存不足2048m,看监控pod使用的内存应该在300-600m之间,其他jvm部分占用500-800m,所以jvm堆真正可以使用的堆只有1G左右。很有可能在完成一次大量的查询时,jvm的堆还没有达到触发GC的条件,而已经达到了pod的limit。所以会看到GC不及时的情况。
3、由于jvm的一些垃圾收集器的问题(我用的是ParallelGC),pod不能回收jvm释放的内存。这一条我只是看了博客,没有验证。

解决方案:

1、修改代码:把查询全量数据修改成,只查询最近七天的数据。
2、增大pod的limit:调成4096m
3、暂时没有更换垃圾收集器,有兴趣的小伙伴可以做个测试。

参考文档:
https://segmentfault.com/a/1190000040050819
https://blog.csdn.net/m0_67393157/article/details/126744386

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/616143
推荐阅读
相关标签
  

闽ICP备14008679号