AliMQ(RockertMQ)源码(五)Consumer的发布订阅和start()方法

一、发布订阅

发布订阅是调用了ComsumerImpl的subscribe方法。

this.subscribeTable.put(topic, listener);
  • 是将topic和listener设置到subscribeTable中,可见,同一个consumer只能设置一个topic对应一个listener。
  • 将tag放入到了ConsumerImpl的rebalanceImpl的subscriptionInner中。

二、start()

ConsumerImpl的start()方法如下

    @Override
    public void start() {
        this.defaultMQPushConsumer.registerMessageListener(new MessageListenerImpl());
        super.start();
    }
  • 第一步是注册了MessageListener
  • 第二步是调用了父类的start()。
    start()先是调用了DefaultMQPushConsumer的start()方法,

三、DefaultMQPushConsumer的start()方法

this.checkConfig();
  • 验证Consumer的各种配置参数是否合法。
this.copySubscription();
  • 上面方法设置到了重试的topic和tag
this.mQClientFactory = MQClientManager.getInstance().getAndCreateMQClientInstance(this.defaultMQPushConsumer, this.rpcHook);
  • MQClientManager是全局的变量,所有的消费者都被设置到了里面,这个方法是将消费的clientId和消费的示例放入到了MQClientManager的factoryTable中
                this.rebalanceImpl.setConsumerGroup(this.defaultMQPushConsumer.getConsumerGroup());
                this.rebalanceImpl.setMessageModel(this.defaultMQPushConsumer.getMessageModel());
                this.rebalanceImpl.setAllocateMessageQueueStrategy(this.defaultMQPushConsumer.getAllocateMessageQueueStrategy());
                this.rebalanceImpl.setmQClientFactory(this.mQClientFactory);
  • 然后是负载均衡器设置了获取消息的策略
switch (this.defaultMQPushConsumer.getMessageModel()) {
                        case BROADCASTING:
                            this.offsetStore = new LocalFileOffsetStore(this.mQClientFactory, this.defaultMQPushConsumer.getConsumerGroup());
                            break;
                        case CLUSTERING:
                            this.offsetStore = new RemoteBrokerOffsetStore(this.mQClientFactory, this.defaultMQPushConsumer.getConsumerGroup());
                            break;
                        default:
                            break;
                    }
                    this.defaultMQPushConsumer.setOffsetStore(this.offsetStore);
  • 设置拉取消息的offset,可以看到广播消息和群组消息获取的offset的策略是不同的
                if (this.getMessageListenerInner() instanceof MessageListenerOrderly) {
                    this.consumeOrderly = true;
                    this.consumeMessageService =
                        new ConsumeMessageOrderlyService(this, (MessageListenerOrderly) this.getMessageListenerInner());
                } else if (this.getMessageListenerInner() instanceof MessageListenerConcurrently) {
                    this.consumeOrderly = false;
                    this.consumeMessageService =
                        new ConsumeMessageConcurrentlyService(this, (MessageListenerConcurrently) this.getMessageListenerInner());
                }
  • 创建消费消息的Service,如果是顺序消息,创建顺序Service,如果是即时消息,创建即时Service。创建的Service中包含三个线程池:
        this.consumeExecutor = new ThreadPoolExecutor(
            this.defaultMQPushConsumer.getConsumeThreadMin(),
            this.defaultMQPushConsumer.getConsumeThreadMax(),
            1000 * 60,
            TimeUnit.MILLISECONDS,
            this.consumeRequestQueue,
            new ThreadFactoryImpl("ConsumeMessageThread_"));

        this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl("ConsumeMessageScheduledThread_"));
        this.cleanExpireMsgExecutors = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl("CleanExpireMsgScheduledThread_"));
  • 分别是处理消息的线程池,默认最小处理线程20,最大处理线程64
  • 定时拉取消息的线程,5s一次
  • 处理超时的消息,5分钟执行一次
mQClientFactory.start();
  • 启动mq的consumer,这个下篇博文单独说下。
this.updateTopicSubscribeInfoWhenSubscriptionChanged();
  • 如果topic的订阅信息发生了改变,则修改订阅信息。
this.mQClientFactory.sendHeartbeatToAllBrokerWithLock();
  • 向broker端发送一次心跳检测,同时上传过滤文件

你可能感兴趣的:(rocketmq,RocketMQ源码解析)