RocketMQ之Pull消费者客户端启动

本文详细剖析RocketMQ中Pull消费者客户端的启动过程,包括设置consumerGroup,DefaultMQPullConsumerImpl的构造,消费者消息模式(广播与集群),消息队列分配算法(平均分配等),offsetStore的初始化以及消费者注册与启动。重点讲解了RebalanceService如何处理消息队列的变更,确保消费者正确处理消息。
摘要由CSDN通过智能技术生成
Pull消费者客户端(主动拉取消息的消费者)即构造了DefaultMQPullConsumer对象,DefaultMQPullConsumer继承了ClientConfig类。我们先看其构造方法
    public DefaultMQPullConsumer(final String consumerGroup, RPCHook rpcHook) {
        this.consumerGroup = consumerGroup;
        defaultMQPullConsumerImpl = new DefaultMQPullConsumerImpl(this, rpcHook);
    }

这里只是简单设置了consumerGroup消费者组名,表示消费者属于哪个组。构造了DefaultMQPullConsumerImpl的实例,DefaultMQPullConsumerImpl的构造方法很简单,只是绑定了DefaultMQPullConsumer、配置了传入的rpcHook。

DefaultMQPullConsumer内部封装了DefaultMQPullConsumerImpl,其中还维护这一些配置信息。这里维护着消费者订阅的topic集合。

    private Set<String> registerTopics = new HashSet<String>();
整个消费者客户端的启动,调用了DefaultMQPullConsumer的start()方法,内部直接调用DefaultMQPullConsumerImpl的start()方法,这个start方法加了synchronized修饰。
    public synchronized void start() throws MQClientException {
        switch (this.serviceState) {
            case CREATE_JUST:
                this.serviceState = ServiceState.START_FAILED;

                this.checkConfig();

                this.copySubscription();

                if (this.defaultMQPullConsumer.getMessageModel() == MessageModel.CLUSTERING) {
                    this.defaultMQPullConsumer.changeInstanceNameToPID();
                }

                this.mQClientFactory = MQClientManager.getInstance().getAndCreateMQClientInstance(this.defaultMQPullConsumer
                                                                                                                , this.rpcHook);

                this.rebalanceImpl.setConsumerGroup(this.defaultMQPullConsumer.getConsumerGroup());
                this.rebalanceImpl.setMessageModel(this.defaultMQPullConsumer.getMessageModel());
                this.rebalanceImpl.setAllocateMessageQueueStrategy(this.defaultMQPullConsumer.getAllocateMessageQueueStrategy());
                this.rebalanceImpl.setmQClientFactory(this.mQClientFactory);

                this.pullAPIWrapper = new PullAPIWrapper(
                    mQClientFactory,
                    this.defaultMQPullConsumer.getConsumerGroup(), isUnitMode());
                this.pullAPIWrapper.registerFilterMessageHook(filterMessageHookList);

                if (this.defaultMQPullConsumer.getOffsetStore() != null) {
                    this.offsetStore = this.defaultMQPullConsumer.getOffsetStore();
                } else {
                    switch (this.defaultMQPullConsumer.getMessageModel()) {
                        case BROADCASTING:
                            this.offsetStore = new LocalFileOffsetStore(this.mQClientFactory, this.defaultMQPullConsumer
                                                                                                        .getConsumerGroup());
                            break;
                        case CLUSTERING:
                            this.offsetStore = new RemoteBrokerOffsetStore(this.mQClientFactory, this.defaultMQPullConsumer
                                                                                                        .getConsumerGroup());
                            break;
                        default:
                            break;
                    }
                    this.defaultMQPullConsumer.setOffsetStore(this.offsetStore);
                }

                this.offsetStore.load();

                boolean registerOK = mQClientFactory.registerConsumer(this.defaultMQPullConsumer.getConsumerGroup(), this);
                if (!registerOK) {
                    this.serviceState = ServiceState.CREATE_JUST;

                    throw new MQClientException("The consumer group[" + this.defaultMQPullConsumer.getConsumerGroup()
                        + "] has been created before, specify another name please." + FAQUrl.suggestTodo(FAQUrl
                                                                                            .GROUP_NAME_DUPLICATE_URL), null);
                }

                mQClientFactory.start();
                log.info("the consumer [{}] start OK", this.defaultMQPullConsumer.getConsumerGroup());
                this.serviceState = ServiceState.RUNNING;
                break;
            case RUNNING:
            case START_FAILED:
            case SHUTDOWN_ALREADY:
                throw new MQClientException("The PullConsumer service state not OK, maybe started once, "
                    + this.serviceState
                    + FAQUrl.suggestTodo(FAQUrl.CLI
在Java的RocketMQ中,如果你想要设置消费者只接收其启动后产生的数据(即Push模式下的新消息),可以按照以下步骤操作: 1. **创建消费者实例**:在创建`ConsumeMessageQueue`实例时,你可以指定一个`MessageModel`,如`CONSUME_MESSAGE_MODEL_PUSH`,它代表Push模式。这告诉RocketMQ消费者应该主动从服务器拉取消息而不是被动接收。 ```java ConsumeMessageQueue consumeMessageQueue = new ConsumeMessageQueue( "queueName", // topic名称 "consumerGroup", // consumer组名 PullRequest.build(new SubscribeInfo(null, "*", MessageModel.CONSUME_MESSAGE_MODEL_PUSH)) ); ``` 2. **配置拉取策略**:虽然RocketMQ默认的Pull策略已经支持只拉取新消息,但你还可以进一步设置具体的拉取间隔,比如使用`PullConsumerConfig`来调整拉取时间间隔。 ```java PullConsumerConfig config = new PullConsumerConfig(); config.setInstanceNameServerAddr("instanceAddress"); // 服务器地址 config.setMessageModel(MessageModel.CONSUME_MESSAGE_MODEL_PULL); config.setConsumeNewMessageOnly(true); // 只拉取新消息 config.setPullInterval(1000 * 60); // 每分钟拉取一次 ``` 3. **启动消费者**:创建好配置后,调用`PullConsumer.createAndStart`方法启动消费者。 ```java PullConsumer consumer = PullConsumer.createPullConsumer(consumeMessageQueue, config); consumer.start(); ``` 这样,消费者只会接收到启动后生产的新消息。请注意,实际应用中可能还需要处理消费者的异常情况和生命周期管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值