Rocketmq之正确设置InstanceName

  引用 (2条消息) rocketmq问题汇总-instanceName参数何时该设置?_MQCloud的专栏-CSDN博客

  1 producer

  默认情况下不需要设置instanceName,rocketmq会使用ip@pid(pid代表jvm名字)作为唯一标示
  

  如果同一个jvm中,不同的producer需要往不同的rocketmq集群发送消息,需要设置不同的instanceName
原因如下:如果不设置instanceName,那么会使用ip@pid作为producer唯一标识,那么会导致多个producer内部只有一个MQClientInstance(与mq交互)实例,从而导致只往一个集群发消息。

  2 consumer

  默认情况下不需要设置instanceName,rocketmq会使用ip@pid作为instanceName(pid代表jvm名字)
如果设置instanceName,rocketmq会使用ip@instanceName作为consumer的唯一标示,此时需要注意instanceName需要不同。
  

  如果consumer设置了instanceName,如果是多台主机上,每一台主机一个JVM进程,这种情况还好。如果是一台主机上,多个JVM进程,且每个consumer的instanceName还相同的情况下,就会出现只有一台consumer消费全部消息的情况。

  因为 rocketmq会使用ip@instanceName作为consumer的唯一标示,这样多个JVM进程中的consumer只有一种cid

  这样在rebalance过程中,会导致只有一个consumer消费所有messagequeue

  AllocateMessageQueueAveragely # allocate

public List<MessageQueue> allocate(String consumerGroup, String currentCID, List<MessageQueue> mqAll,
        List<String> cidAll) {
        if (currentCID == null || currentCID.length() < 1) {
            throw new IllegalArgumentException("currentCID is empty");
        }
        if (mqAll == null || mqAll.isEmpty()) {
            throw new IllegalArgumentException("mqAll is null or mqAll empty");
        }
        if (cidAll == null || cidAll.isEmpty()) {
            throw new IllegalArgumentException("cidAll is null or cidAll empty");
        }

        List<MessageQueue> result = new ArrayList<MessageQueue>();
        if (!cidAll.contains(currentCID)) {
            log.info("[BUG] ConsumerGroup: {} The consumerId: {} not in cidAll: {}",
                consumerGroup,
                currentCID,
                cidAll);
            return result;
        }

        int index = cidAll.indexOf(currentCID);
        int mod = mqAll.size() % cidAll.size();//cidAll实际只有一个成员 mod 就是0
        int averageSize =
            mqAll.size() <= cidAll.size() ? 1 : (mod > 0 && index < mod ? mqAll.size() / cidAll.size()
                + 1 : mqAll.size() / cidAll.size());
        int startIndex = (mod > 0 && index < mod) ? index * averageSize : index * averageSize + mod;//startIndex就是0
        int range = Math.min(averageSize, mqAll.size() - startIndex);
        for (int i = 0; i < range; i++) {
            result.add(mqAll.get((startIndex + i) % mqAll.size()));
        }
        return result;
    }

  这样就是永远一个consumer消费了所有messageQueue。

  不过这种情况也比较极端,一台主机跑一个系统下的多个JVM这不多见

posted on 2021-08-31 11:18  MaXianZhe  阅读(2168)  评论(0编辑  收藏  举报

导航