内存溢出(Out Of Memory,简称OOM)是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。此时程序就运行不了,系统会提示内存溢出,有时候会自动关闭软件,重启电脑或者软件后释放掉一部分内存又可以正常运行该软件,而由系统配置、数据流、用户代码等原因而导致的内存溢出错误,即使用户重新执行任务依然无法避免。
JVM发生OOM异常可能是以下几种情况: Java堆溢出、虚拟机栈和本地方法栈溢出、方法区和运行时常量池溢出、本机直接内存溢出 。这几种情况分别由不同的原因引起。
而在真实的业务场景中,环境往往更加复杂。今天,堆堆就带大家学习几个OOM问题排查实战案例,通过几位作者记录的真实案例,提醒自己避免踩坑,也顺便复习相关知识点。
1.体验了一把线上CPU100%及应用OOM的排查和解决过程
作者:阿飞云 heapdump.cn/article/166… 概述: 作者在收到应用异常告警后,登录了出现问题的服务器进行检查,在查看服务的日志时发现服务OOM了,紧接着使用Top命令查看系统中各个进程的资源占用状况,发现有一个进程CPU使用率达到了300%,然后查询该进程下所有线程的CPU使用情况并保存堆栈数据。根据前述操作,获取了出现问题的服务的GC信息、线程堆栈、堆快照等数据之后,使用HeapDump社区提供的XElephant进行分析,发现是InMemoryReporterMetrics引起的OOM,进一步发现出现问题的这个服务依赖的zipkin版本较低,将其升级后解决了问题。
亮点:虽然本文描述和解决的不是罕见的疑难杂症,但排查思路清晰,过程完整,还推荐了排查工具,适合新手阅读学习。
2.一次容器化springboot程序OOM问题探险
作者:侠梦 heapdump.cn/article/158…
概述:作者被告知一个容器化的java程序每跑一段时间就会出现OOM问题,首先查日志并未发现异常;然后通过JStat查看GC情况,发现GC情况正常但ByteBuffer对象占用最高(异常点1);接着通过JStack查看线程快照情况,发现创建了过多kafka生产者(异常点2);最后通过编写Demo程序验证猜想,确定问题是业务代码中循环创建Producer对象导致的。
亮点:排查过程清晰明了,工具使用娴熟,验证过程快速准确。
3.一次百万长连接压测 Nginx OOM 的问题排查分析
作者:挖坑的张师傅 heapdump.cn/article/433…
概述: 作者在一次百万长连接压测中,发现32C 128G的四台Nginx频繁出现OOM。发现问题后首先查看了 Nginx 和客户端两端的网络连接状态,首先怀疑是jmeter客户端处理能力有限,有较多消息堆积在中转的Nginx处,于是dump了nginx的内存查看,坚定了是因为缓存了大量的消息导致的内存上涨;随后查看了 Nginx 的参数配置,发现proxy_buffers 这个值设置的特别大;然后模拟了upstream 上下游收发速度不一致对Nginx内存占用的影响。最后将proxy_buffering 设置为 off并调小了 proxy_buffer_size 的值以后,Nginx的内存稳定了。
亮点:作者排查思路清晰,工具使用、参数调节十分娴熟,对底层原理和源码理解深刻,无论是经验还是态度都十分值得学习参考。