记一次内存溢出的问题处理过程

记一次内存溢出的问题处理过程

概述

OOM是每个Java程序员都可能遇到的问题,但很多问题可能其本身并没有考虑好,或者是采用了一种类似于简单增大内存的处理机制,这种可能部分上能解决问题,但要是具体要原因,那可能大部分程序员都不会很清楚。
本篇文章以自己的实际工作为切入点,从一次内存溢出的处理过程来简要说明下如何处理。

需求

系统非常复杂,由于工作原因不好说明具体是什么,将其处理过程简单抽象一下,大概如下:
简单流程抽象
其中队列1用于暂时缓存MQ的消息,防止积压;队列2用于业务逻辑处理,将队列1中的数据处理为一种合理的数据结构放入队列3,在队列3中该数据结构即合理的。队列3的处理是最终的逻辑处理过程,之前的那几种都是为其服务。

工具

主要的使用工具就是JProfile,我使用的是9.x版本,网上找的可用激活码。

现象

这个问题的来源其实并非做性能分析,而是做大数据量处理。项目结项的要求是可以达到亿级请求处理,因此就做了一个长期监测,这一监测发现内存的问题非常严重,经常跑一会儿(半个小时)系统就因为内存问题卡住不动。
于是把内存设置为256M(最大最小均为256M),通过JProfile启动程序进行分析:
256M内存情况
从上图可以发现两点:

  • 1、256M的内存是可用的,前5分钟的正常业务逻辑很显然说明了这点;
  • 2、5min时候GC失败,意味着没有可GC的资源,那么就存在两种可能,一种是对象不断增加,并且不需要释放,另一种则是存在内存泄漏。
分析

猜测是不可能完成这项工作的,当然必然的推理是有必要的,下面首先说明一下JProfile对这种问题的处理思路。

  • 1、找内存规律;内存一直变大没有释放那么这部分对象占用的内存是比较大的,并且内存占有量基本不会下降;
  • 2、找源头;根据1找到这些对象之后,需要再找到这些对象的来源,也就是产生他们的地方,这才是我们最终要处理的那部分逻辑;
  • 3、分析代码改改改。 最后肯定是脱离不了分析代码修改这个阶段,那就需要根据2的提示,完成这一目标。
1)找内存规律

打开Live memory 的All Objects,如下图所示:
在这里插入图片描述

我们可以从图中看到最右侧那个占有量最大的几个(按照size排序),一般就是我们需要分析的对象,像图中的byte[]这个就是需要分析的,但是这种对象不同于其他的对象,其他的对象我们可以通过类名就能简单分析出大概是什么对象,但byte[]这种就稍微复杂一点。

2)找源头

右键选中该对象,然后点击“Show Selection In Heap Walker”这个按钮,我们就可以进入这个对象的专属分析界面:
在这里插入图片描述
专属分析界面如下:
在这里插入图片描述
这个时候我们再选中该对象,点击那个“Selected Instances”按钮
在这里插入图片描述
点击弹窗中的Allocations单选按钮,选择Allocation tree,这个意思是调用树。也就是整个调用到该对象的过程。
在这里插入图片描述

这个图片可能很难分析,需要将他们点开,找到那个调用占比最高的那部分代码:
在这里插入图片描述
这样我们就发现其实是rabbitmq的readFrom方法搞的鬼。

3)分析代码改改改

为什么会是rabbitmq的问题?
我们的队列1使用的是rabbitmq,采用的方式就是每次消费的消息放入队列中, 该队列使用的是LinkedBlockedQueue,这个队列很明显是不限长的。
经过分析发现是需要改动的点还比较多:

  • 1、rabbitmq未设置Qos,导致消费过快,(rabbitmq默认是以最快的方式发送给消费者);
  • 2、队列1和队列2都采用了未限长的队列,这两个队列需要协调,因此都需要做调整;
  • 3、队列3使用的是disruptor,后来了解到时因为其RingBuffer的长度导致;
结果

最终经过调整,把三级队列修改为两级,全部采用Disruptor来实现,如下:
在这里插入图片描述

最终的效果图变成了如下这样:
在这里插入图片描述
也是在256M的情况下结果,堪称完美~~~~~~~

欢迎跟帖交流~~~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值