RocketMq实战篇:Docker部署Consumer客户端造成的RocketMQ的一场血案(重复消费和NOT_CONSUME_YET)

Posted keep-go-on

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RocketMq实战篇:Docker部署Consumer客户端造成的RocketMQ的一场血案(重复消费和NOT_CONSUME_YET)相关的知识,希望对你有一定的参考价值。

案情描述

生产者发送消息后,消费者对消息要么不能消费(NOT_CONSUME_YET),要么出现重复消费。在集群模式(CLUSTERING)消息模式下,同一个消息应当向一个消费组下的其中一个消费者发送消息,而不是向消费组下的所有消费者发送消息。而血案就造成了这种重复消费。

在2021-03-16 的代码提交时已经解决了该问题。

这里的修改,解决了什么 ?

答 : 默认实例名后面加入了时间戳(纳秒的时间戳哦)防止实例名称重复。

防止实例名重名有什么作用 ?

答 : 客户端ID由客户端IP + 实例名(instanceName) + unitName 。源代码如下 :

    public String buildMQClientId() 
        StringBuilder sb = new StringBuilder();
        sb.append(this.getClientIP());

        sb.append("@");
        sb.append(this.getInstanceName());
        if (!UtilAll.isBlank(this.unitName)) 
            sb.append("@");
            sb.append(this.unitName);
        

        return sb.toString();
    

客户端Id重复会造成什么问题 ?

答 : 会造成消息NOT_CONSUME_YET 。当然这种情况仅仅会出现在一个消费组有多个消费者,并且使用Docker进行部署消费者的情况。

为什么docker部署会造成客户端Id重复 ?

答:使用docker部署程序,由于docker内是一个相对隔离的环境,并且docker容器内大多数仅仅启动一个进程,而docker启动第一个进程的进程ID都是 1,因此PID是相同的,由于docker内部网络环境也是相对独立的,造成获取的客户端IP也是相同的。这时如果没有设置unitName,就会造成多个消费者客户端客户端ID相同。

为什么消费者客户端ID相同会造成NOT_CONSUME_YET

答 : 名称服务是KV方式存储信息。消费者会注册给命名服务器。如果ID重复,那么名称服务器就无法根据客户端ID找到正确的消费者客户端(也可能能找对,找对了就能消费)。

解决方案:

  • 配置unitName。
  • 客户化InstanceName

以上是关于RocketMq实战篇:Docker部署Consumer客户端造成的RocketMQ的一场血案(重复消费和NOT_CONSUME_YET)的主要内容,如果未能解决你的问题,请参考以下文章

RocketMq实战篇:Docker部署Consumer客户端造成的RocketMQ的一场血案(重复消费和NOT_CONSUME_YET)

架构实战篇:Spring Boot 集成 RocketMQ

Zabbix实战之部署篇使用Docker部署Zabbix 6.2.7监控平台

云原生时代必须具备的核心技能之Docker高级篇(Docker实战之SpringBoot项目部署)

「实战篇」开源项目docker化运维部署-搭建mysql集群

RocketMQ===》docker部署RocketMQ