一、问题

最近一个Spring Cloud微服务项目中定义的RocketMQ Consumer Bean不能正常触发消息消费。问题发生在测试环境。

这个功能以前是好的,生产环境和预发环境也是正常的。

二、定位

RocketMQ是阿里开源的用Java实现的消息中间件,广泛用于金融、电商等领域。

检查了一下Consumer Bean的定义,一切正常。按API要求定义了groupId,NameServer地址,Topic,Tag和Listener;Consumer Bean启动也正常,没有任何异常。

但是生产者成功发送消息后,Listener没有消费任何消息。

登陆RocketMQ管理控制台,看到Topic和消费组都存在。但是消费组下面从Consume Detail点击进去看不到订阅的topic。

也就是说虽然Consumer Bean虽然subscribe订阅topic成功了,实际没有成功!并且没有任何异常!

我们RocketMQ和应用部署比较复杂,使用了Docker Compose和Swarm,一开始怀疑是网络问题,因为代码在预发和生产环境是正常的,只是最近在开发测试环境消费失败。

但是奇怪的是其他消费组和topic也正常,说明RocketMQ也应该正常,问题应该在应用部署或者应用自身。

不同环境、不同topic和消费组对比一下后,还发现一个问题。出问题的消费组除了没有订阅预期的topic以外,还看到另外一个奇怪的topic。一开始没有特别关注这一点。

RocketMQ作者也不熟,除了面试八股文中背的“事务消息”,实操为0。各种AI Chat一圈无果。地铁上想到这两天“千问”APP火出圈了,都是阿里的亲儿子,知根知底,问问“千问”APP看。

Bingo,“千问”给的第一个方案让我想到前面消费组下面奇怪的topic,感觉就是这个原因了。

关闭非预期topic对应的消费应用后,重新启动我们消费应用,发现topic已经能正常订阅了。消费消息也就正常了。

三、结论

RocketMQ要求同一个消费组(Group ID)下的所有消费者实例,必须订阅完全相同的topic和Tag。否则会出现topic注册失败,消息不能消费的问题。

这点其实和Kafka的设计规范一致:同一个消费者组内的所有消费者必须订阅相同的主题。想想也对,如果topic不同,分区、再平衡策略和Offset管理就不好处理了。

“All consumers in the same group must subscribe to the same topics.”