实验(二)

实验步骤

准备

 创建的topicA、topicB,每个都是16个消息队列;

 创建了同一个消费者组:ntm-hxy-group

 默认消息模式:负载均衡

消费者启动

消费者启动公共方法如下:

/**
     * 消费者启动
     * @param pushConsumerGroup 消费者组
     * @param namesrvAddr nameServer地址
     * @param topic topic
     * @param topic topic2
     * @return {@link DefaultMQPushConsumer}
     * @author Green
     * @date 2022/4/13 4:24 下午
     */
    public static DefaultMQPushConsumer createConcurrentlyPushConsumer(String pushConsumerGroup,
                                                                       String namesrvAddr, String topic, String topic2) throws Exception {
        DefaultMQPushConsumer pushConsumer = new DefaultMQPushConsumer(pushConsumerGroup);
        pushConsumer.setNamesrvAddr(namesrvAddr);
        pushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);

        // 过滤方式一、TAG方式
        pushConsumer.subscribe(topic, "*");
        if (topic2 != null) {

            pushConsumer.subscribe(topic2, "*");
        }

        // 并发消息监听接口
        pushConsumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                System.out.println("test!!!");
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        pushConsumer.start();
        return pushConsumer;
    }

 启动第一个消费者(clientId1):

 1 /**
 2      * 消费者启动测试
 3      * @param args
 4      * @author Green
 5      * @date 2022/4/13 4:25 下午
 6      */
 7     public static void main(String[] args) throws Exception {
 8         String nameAddress = "192.168.11.180:9876;192.168.11.181:9876;192.168.11.182:9876";
 9         DefaultMQPushConsumer concurrentlyPushConsumer2 =
10                 createConcurrentlyPushConsumer("ntm-hxy-group", nameAddress, "topicA", "topicB");
11 
12     }

启动第二个消费者(clientId2):

/**
     * 消费者启动测试
     * @param args
     * @author Green
     * @date 2022/4/13 4:25 下午
     */
    public static void main(String[] args) throws Exception {
        String nameAddress = "192.168.11.180:9876;192.168.11.181:9876;192.168.11.182:9876";

        DefaultMQPushConsumer concurrentlyPushConsumer1 =
                createConcurrentlyPushConsumer("ntm-hxy-group", nameAddress, "topicA", null);

    }

 

 消费者1、2属于同一个消费组,消费者1订阅了topicA、topicB,消费者2只订阅了topicA

打断点

因为需要在idea中启动两个main方法,所以每个断点都采用多线程的方式,如下:

断点位置如下:

①:org.apache.rocketmq.client.impl.consumer.RebalanceImpl#rebalanceByTopic  line:261

 

 这个目的是为了看,当前消费者负载均衡时,通过topic得到的消息队列mqSet、通过group得到的所有client的集合cidAll的值。

②org.apache.rocketmq.client.impl.consumer.RebalanceImpl#rebalanceByTopic  line:293

 

 因为在上图箭头出,就是采用负载均衡策略,得到该消费者分配的消息队列,所以这个断点就是看具体分配的消息队列有哪些。

 

结论

为了解决实验(一)博客最后的疑问:

因为client1订阅了topicA、topicB,所以本地缓存中有topicA和topicB队列信息,断点①是通过本地缓存得到消息队列信息mqSet的,如下:

  • 在client1中通过断点①可以得到topicA的16个消息队列,通过group可以得到2个clientId,所以在断点②处分配到了8个队列进行消费;
  • 在client1中通过断点①可以得到topicB的16个消息队列,通过group可以得到2个clientId,所以在断点②处分配到了8个队列进行消费;

因为client2只订阅了topicA,本地缓存中只有topicA的队列信息,如下:

  • 在client2中通过断点①可以得到topicA的16个消息队列,通过group可以得到2个clientId,所以在断点②处分配到了8个队列进行消费;
  • 在client2中因为本地缓存并没有topicB信息,所以断点①处得到的mqSet是空的,也就不会进行负载均衡操作进行分配,所以这就导致了topicB的另外8个队列并没有消费者进行消费,会一直堆积;

注意:虽然心跳会不断的修改服务端订阅信息(即远程clientId订阅的topic会改变,有时候有topicA、topicB,有时候只有topicA),但是各个消费端clientId本地缓存的订阅信息是不会变的,所以客户端负载均衡绑定的消费队列不会变的。

 

  

 

 
posted @ 2022-04-18 15:50  迷走神经  阅读(35)  评论(0编辑  收藏  举报