前言
OutOfMemoryError 问题相信很多朋友都遇到过,相对于常见的业务异常(数组越界、空指针等)来说这类问题是很难定位和解决的。

本文以最近碰到的一次线上内存溢出的定位、解决问题的方式展开;希望能对碰到类似问题的同学带来思路和帮助。

主要从表现-->排查-->定位-->解决 四个步骤来分析和解决问题。

表象
最近我们生产上的一个应用不断的爆出内存溢出,并且随着业务量的增长出现的频次越来越高。

该程序的业务逻辑非常简单,就是从 Kafka 中将数据消费下来然后批量的做持久化操作。

而现象则是随着 Kafka 的消息越多,出现的异常的频次就越快。由于当时还有其他工作所以只能让运维做重启,并且监控好堆内存以及 GC 情况。

重启大法虽好,可是依然不能根本解决问题。

排查
于是我们想根据运维之前收集到的内存数据、GC 日志尝试判断哪里出现问题。

结果发现老年代的内存使用就算是发生 GC 也一直居高不下,而且随着时间推移也越来越高。

结合 jstat 的日志发现就算是发生了 FGC 老年代也已经回收不了,内存已经到顶。

甚至有几台应用 FGC 达到了上百次,时间也高的可怕。

这说明应用的内存使用肯定是有问题的,有许多赖皮对象始终回收不掉。

定位
由于生产上的内存 dump 文件非常大,达到了几十G。也是由于我们的内存设置太大有关。

所以导致想使用 MAT 分析需要花费大量时间。

因此我们便想是否可以在本地复现,这样就要好定位的多。

为了尽快的复现问题,我将本地应用最大堆内存设置为 150M。

然后在消费 Kafka 那里 Mock 为一个 while 循环一直不断的生成数据。

同时当应用启动之后利用 VisualVM 连上应用实时监控内存、GC 的使用情况。

结果跑了 10 几分钟内存使用并没有什么问题。根据图中可以看出,每产生一次 GC 内存都能有效的回收,所以这样并没有复现问题。

没法复现问题就很难定位了。于是我们 review 代码,发现生产的逻辑和我们用 while 循环 Mock 数据还不太一样。

查看生产的日志发现每次从 Kafka 中取出的都是几百条数据,而我们 Mock 时每次只能产生一条。

为了尽可能的模拟生产情况便在服务器上跑着一个生产者程序,一直源源不断的向 Kafka 中发送数据。

果然不出意外只跑了一分多钟内存就顶不住了,观察左图发现 GC 的频次非常高,但是内存的回收却是相形见拙。

同时后台也开始打印内存溢出了,这样便复现出问题。

解决
从目前的表现来看就是内存中有许多对象一直存在强引用关系导致得不到回收。

于是便想看看到底是什么对象占用了这么多的内存,利用 VisualVM 的 HeapDump 功能可以立即 dump 出当前应用的内存情况。

结果发现 com.lmax.disruptor.RingBuffer 类型的对象占用了将近 50% 的内存。

看到这个包自然就想到了 Disruptor 环形队列。

再次 review 代码发现:从 Kafka 里取出的 700 条数据是直接往 Disruptor 里丢的。

这里也就能说明为什么第一次模拟数据没复现问题了。

模拟的时候是一个对象放进队列里,而生产的情况是 700 条数据放进队列里。这个数据量是 700 倍的差距。

而 Disruptor 作为一个环形队列,再对象没有被覆盖之前是一直存在的。

我也做了一个实验,证明确实如此。

我设置队列大小为 8 ,从 0~9 往里面写 10 条数据,当写到 8 的时候就会把之前 0 的位置覆盖掉,后面的以此类推(类似于 HashMap 的取模定位)。

所以在生产上假设我们的队列大小是 1024,那么随着系统的运行最终肯定会导致 1024 个位置上装满了对象,而且每个位置是 700 个!

于是查看了生产上 Disruptor 的 RingBuffer 配置,结果是:1024*1024。

这个数量级就非常吓人了。

为了验证是否是这个问题,我在本地将该值换为 2 ,一个最小值试试。

同样的 128M 内存,也是通过 Kafka 一直源源不断的取出数据。通过监控如下:

跑了 20 几分钟系统一切正常,每当一次 GC 都能回收大部分内存,最终呈现锯齿状。

这样问题就找到了,不过生产上这个值具体设置多少还得根据业务情况测试才能知道,但原有的 1024*1024 是绝对不能再使用了。

总结
虽然到了最后也就改了一行代码(还没改,直接修改配置),但这排查过程我觉得是有意义的。

也会让大部分觉得 JVM 这样的黑盒难以下手的同学有一个直观的感受。

转载于:https://blog.51cto.com/13842645/2166013

小编带你进入强如 Disruptor 也发生内存溢出?相关推荐

  1. 强如 Disruptor 也发生内存溢出?

    前言 OutOfMemoryError 问题相信很多朋友都遇到过,相对于常见的业务异常(数组越界.空指针等)来说这类问题是很难定位和解决的. 本文以最近碰到的一次线上内存溢出的定位.解决问题的方式展开 ...

  2. for循环十万条数据内存溢出_强如 Disruptor 也发生内存溢出?

    前言 OutOfMemoryError 问题相信很多朋友都遇到过,相对于常见的业务异常(数组越界.空指针等)来说这类问题是很难定位和解决的. 本文以最近碰到的一次线上内存溢出的定位.解决问题的方式展开 ...

  3. 小编带你两图看清北京大厂公司、码农分布——谷歌,微软,百度,腾讯,阿里,滴滴,美团,头条,独角兽

    小编带你两图看清北京大厂公司.码农分布--谷歌,微软,百度,腾讯,阿里,滴滴,美团,头条 ​ 北京一二线大厂公司.码农分布 年关将至,意味着2021年即将过去,2022年即将到来 现在,就是大家开始为 ...

  4. 易语言简单易学,为何无人问津,国产编译语言究竟怎么样?小编带你看

    看了昨天大家在文章下面的评论,小编在这里感谢大家的认可,也对大家的疑问和职责做出了一些检讨,看到大家在讨论易语言的时候自己也是有些感触,今天就来带大家深入的了解一下这个国产编译语言. 作为一款国产的编 ...

  5. [日推荐]『台湾景点大全』小编带你游台湾!

    2019独角兽企业重金招聘Python工程师标准>>> 小编今天要带大家去台湾玩一玩! 你问我怎么去? 用这个呀-- 台湾景点大全 简介:台湾景点大全,方便查询台湾的所有景点,攻略路 ...

  6. 分层和分段用什么符号_小编带你学直播——后牙树脂分层堆塑

    后牙龋损过大,患者又不想做冠修复,树脂修补真的能挽救被龋坏侵蚀的牙体吗?补牙看起来简单,但是补好却难,同事用分层堆塑补的后牙窝沟分明,有点想学...本周小编为你推荐吕春阳老师--<后牙树脂分层堆 ...

  7. 话费对接充值平台_手机话费误充给他人怎么办?小编带你找运营商要回来

    误充手机话费能要回来?这事儿听着有些不可思议,可就小编这两天的亲身经历而言,还真的要回来了!今天这个技巧分享,可以点赞.转发.留言三连击不? 01 被误会的微信,充错的手机话费 月初充话费是件再普通不 ...

  8. 好久不见!~小编带给大家古老的vue搭配kityMinder使用方法

    其实kityMinder是一个很强大的思维脑图的配置,如果我们想用代码去实现脑图其实很简单.我们可以看下某度脑图和github的在线地址.封装了很多使用方法.那么小编就废话不多说,直接上代码. ①.首 ...

  9. 小编带你一起揭开DLL木马的神秘面纱(转)

    在这个万"马"奔腾的时代,网络上充斥着各种各样的木马,不过随着杀毒技术的进步和大家防毒意识的提高,传统木马已渐渐失去市场,而DLL木马则"与时俱进"以其强大的生 ...

最新文章

  1. 是否能领先e步 浅析SSD中的eTLC和eMLC颗粒
  2. 借助 Debugging Tools 分析蓝屏故障原因
  3. LeetCode-二分查找-69. Sqrt(x)
  4. angular $resource参数占位符释疑
  5. [css] 如何使用CSS3的属性设置模拟边框跟border效果一样?
  6. 谈谈个人代码对团队合作影响
  7. php 利用个人邮箱,利用 Composer 完善自己的 PHP 框架(二)——发送邮件
  8. MySQL (13)---查询数据
  9. centos7下cups + samba共打印服务
  10. java 引用 判断_[JAVA基础]你知道Java的四种引用类型吗
  11. Linux SendMail发送邮件失败诊断案例(四)
  12. 一带一路”建设的助力者——刘岳霖
  13. docker tomcat 多开 实例_Docker 快速验证 tomcat 单机多实例方案
  14. python- selenium-快眼看书-林深终有路
  15. 将NX,JT, step等一些常见3维格式文件直接发布到网页上,可在线浏览
  16. 许昌一高2021年高考成绩查询,2020年许昌高中高考成绩怎么样啊??
  17. 企业管理决策之金字塔思维
  18. 周浩正:写给编辑人的信 关于“编辑”
  19. Java代码审计——WebGoat CSRF (上)
  20. 正则匹配以什么开头、以什么结尾,以非什么开头,以非什么结尾

热门文章

  1. Sourse Insight使用教程及常见的问题解决办法
  2. 天堂Lineage(單機版)從零開始架設教學
  3. python基础学习-5(包与模块)
  4. 一笔画问题【数据结构-图论】
  5. HTTP POST慢速DOS攻击初探
  6. HTTP中Get与Post的区别
  7. 跨平台PHP调试器设计及使用方法——探索和设计
  8. WMI技术介绍和应用——接收事件
  9. 使用VC内嵌Python实现的一个代码检测工具
  10. Ubuntu上配置VS Code调试C++