一次线上OOM与RocketMQ消费者源码分析

1、背景介绍

这是一个临时文件的清洗服务,主要使用消费者生产者模型

清洗方式为分段清洗,因为清洗数据量过大,所以需要对数据进行分段以方便容错处理。

清洗服务模型如图:

image.png 每个消费者实例中一个消费者进程执行一段的清洗任务需要的时间大约为15分钟

生产者生产消息的速度远大于消费速度。

2、问题出现

清洗程序在凌晨启动,但是启动没几分钟后便收到疯狂告警: image.png

看日志信息来说,就是疯狂GC但是回收不到垃圾,堆内存不够了。

那接下来就看看JVM的监控情况:

image.png

image.png

确实堆内存不够用了,那为什么不够用呢?

3、问题定位与解决

1)堆内存dump

在设置了 -XX:HeapDumpPath=/app/logs -XX:+HeapDumpOnOutOfMemoryError 后,JVM会在发生OOM的时候将当时的内存状况dump下来。

那接下来我们就分析一波内存情况

使用工具:jvisualvm

2)出现问题的线程

image.pngimage.png 看样子就是在拷贝byte数组时候出现了内存不够用。

那接下来看看堆中是哪些实例占用了过多的内存

3)堆分析

先按照大小排序:

image.png 这个byte数组大概占用了93%的内存,那问题差不多就出在这儿了。

点进去看看这个实例的引用是什么:

image.png 按照从大到小排序,看到这个MessageClientExt就基本上可以猜到,是不是消息体过多导致的?

下面我们去源码分析一波,这个消息体到底是如何存在与消失的。

4)RocketMQ消费者源码分析(rocketmq-client:4.3.2)

在这之前,我们先看看RocketMQ的一些关键模型图:

Topic与Queue的关系:

每个Topic在不同的Broker内可以有不同数量的Queue,这全部的Queue都需要被消费者连接。

生产者投递消息会根据策略选择Queue进行投递,具体什么策略大家可以自行Google一下,这里不过多介绍。

image.png 目前我们线上设置的是10个broker,每个broker有16个queue。

Queue与消费者实例的关系:

这里为了简单起见,将所有的Broker合并为一个。

根据RebalanceService的策略,会把Broker的Queue与消费者实例中本地的ProcessQueue一一对应。

image.png

消费逻辑

这里重点关注消息何时被拉到本地,忽略offset怎么更新、顺序消费、消费失败等情况。

image.png

消息体流转源码分析

1、消息拉取到后存放在哪儿?

org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl#pullMessage

// 首先进行一些限制性的校验,重点关注defaultMQPushConsumer.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值