前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RocketMQ Spring Starter消费堆积引发的系统思考和处理(1)

RocketMQ Spring Starter消费堆积引发的系统思考和处理(1)

作者头像
小伟
发布2022-07-24 09:40:25
7490
发布2022-07-24 09:40:25
举报
文章被收录于专栏:魔都程序缘魔都程序缘

在使用RocketMQ的过程中,消费堆积问题是不可避免的问题。这次借机分享下如何系统思考和解决问题,各位方家指正。

我本地已经复现了该问题,这里以一个复现的app做分享和解释。主要包含

  1. 复现问题
  2. 问题描述
  3. 问题分析
  4. 翻看源码确认问题
  5. 解决问题
    1. 临时解决 --- 变通解
    2. 长期解决 --- 提PR彻底解
  6. 周边问题确认

本文涉及rocketmq dashboard代码、rocketmq admin tool代码、broker代码、client代码、client&broker心跳源码等,建议坐地铁时翻看,有问题随时留言。

1. 复现问题:这一步靠经验吧。

https://github.com/rocketmq101/spring-issue-405

2. 问题描述

用户在使用RocketMQ Spring 2.2.1的时候发现消费堆积,异常截图如下:

消费详情一直不变,并且始终消费不到queue 0, queue 1:

消费者实例:启动了一个push消费者,消费者client却有两个。

用户使用的代码:

用户配置:

3. 初步分析

某种原因导致启动了两个消费者实例,并且会导致订阅关系不一致。

可能性1:

根据以往的经验,订阅关系不一致,会导致全部的消费者在分配queue-消费者实例的时候出现混乱,导致订阅错乱,所以有的queue没有消费者消费。

此时重温下什么是订阅关系:在一个消费者组中,消费者组-topic-tag在每个消费者实例启动时必须保持一致。

经过排查,这个消费者订阅关系一致,排除掉。

可能性2:

Push消费者和Pull消费者同时存在。导致用户使用的Push消费者只消费到了一部分queue,另一部分由Pull消费者分配了,但是没有展示。

为什么这么猜测?

首先,源自于flink消费kafka的逻辑,在flink消费kafka时,kafka-manager上是看不到消费者的。flink消费kafka实际是pull的,猜测RocketMQ和kafka这里逻辑一样。

其次,RocketMQ队列分配逻辑:每个消费者将自己注册到broker中,启动reblance时,全部的queue按照一定的原则分配给全部的消费者实例。Pull和Push消费者是否一起当作消费者分配了不同的队列呢?

这个猜测最后通过排查rocketmq-dashboad、rocketmq broker、rocketmq client的代码后确认了此逻辑。

4. 源码翻看。

4.1 RocketMQ Spring源码确认问题

翻看github issue,可以找到:https://github.com/apache/rocketmq-spring/issues/450有相似问题。这个问题目前笔者已经提PR修复了,欢迎大家使用新版本的RocketMQ Spring。

翻看源码后,确认了一个恶心的逻辑。

恶心逻辑:如果rocketmq-spring配置项中包含了下面三个配置项时,会默认启动一个DefaultLitePullConsumer实例。

代码语言:javascript
复制
rocketmq.name-server=127.0.0.1:9876
rocketmq.consumer.group=test-group
rocketmq.consumer.topic=test-topic

总结:所以可以解释通现象中明明只配置了一个PushConsumer,但是启动了2个Client实例。

4.2 Broker4.9.3 源码,确认日志。

其实消费者在启动注册到Broker的时候, 会打印日志:

如果启动很久了,日志可能被删除了,重启下消费者就会看到。

5. 问题处理

如果处理呢?在配置RocketMQ Spring 时,只要以下三个配置项不同时存在就行了(这里吐槽Spring的条件注解,非常好用,也非常容易滋生暗病)

代码语言:javascript
复制
rocketmq.name-server=127.0.0.1:9876
rocketmq.consumer.group=test-group
rocketmq.consumer.topic=test-topic

一般处理到这里就完了。下面是我提的两个问题:

第一个问题:如何彻底解这个问题呢?

当然是提交代码,合并到社区,新版本会彻底修掉这个bug,大家也不会再遇到这个问题。

目前代码已经合并到社区,欢迎大家阅读指正:

https://github.com/apache/rocketmq-spring/pull/459。

这个修改的指导思想是:配置项功能需要简单、明确,一个配置项就干一个事情。

第二个问题:在消费详情中,为什么Pull消费者在Dashboard中不显示消费者client和queue的关系信息呢?

实际下图的空白中,是Pull消费者消费的,却没有consumerClient。

第三个问题:在消费者实例列表中,明明Pull和Push消费者的ConsumerType不一样,为什么这里只显示了CONSUME_ACTIVELY(Pull)

CONSUME_ACTIVELY为什么表示Pull,请看代码:

第二,三个问题将在下一篇继续介绍。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 魔都程序缘 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档