RocketMQ之消费者启动与消费流程

一、简介

1.1 RocketMQ 简介

RocketMQ是由阿里巴巴开源的分布式消息中间件,支持顺序消息、定时消息、自定义过滤器、负载均衡、pull/push消息等功能。RocketMQ主要由 Producer、Broker、Consumer 、NameServer四部分组成,其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息。NameServer充当名字路由服务,整体架构图如下所示:

roducer:负责生产消息,一般由业务系统生产消息,可通过集群方式部署。RocketMQ提供多种发送方式,同步发送、异步发送、顺序发送、单向发送。同步和异步方式均需要Broker返回确认信息,单向发送不需要。

Consumer:负责消费消息,一般是后台系统负责异步消费,可通过集群方式部署。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序。提供pull/push两者消费模式。

Broker Server:负责存储消息、转发消息。RocketMQ系统中负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备,存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等。

Name Server:名字服务,充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个NameServer实例组成集群,相互独立,没有信息交换。

本文基于Apache RocketMQ 最新版本主要讲述RocketMQ的消费者机制,分析其启动流程、pull/push机制,消息ack机制以及定时消息和顺序消息的不同。

1.2 工作流程

(1)启动NameServer。

NameServer起来后监听端口,等待Broker、Producer、Consumer连上来,相当于一个路由控制中心。

(2)启动Broker。

跟所有的NameServer保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有Topic信息。注册成功后,NameServer集群中就有Topic跟Broker的映射关系。

(3)创建Topic。

创建Topic时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic。

(4)Producer发送消息。

启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic存在哪些Broker上,轮询从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息。

(5)Consumer消费消息。

跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息。

二、消费者启动流程

官方给出的消费者实现代码如下所示:

public class Consumer {
    public static void main(String[] args) throws InterruptedException, MQClientException {
        // 实例化消费者
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("TestConsumer");
        // 设置NameServer的地址
        consumer.setNamesrvAddr("localhost:9876");
        // 订阅一个Topic,以及Tag来过滤需要消费的消息
        consumer.subscribe("Test", "*");
        // 注册回调实现类来处理从broker拉取回来的消息
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
                // 标记该消息已经被成功消费
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        // 启动消费者实例
        consumer.start();
        System.out.printf("Consumer Started.%n");
    }
}

下面让我们来分析消费者在启动中每一阶段中做了什么吧,let’s go.

2.1 实例化消费者

第一步主要是实例化消费者,这里采取默认的Push消费者模式,构造器中参数为对应的消费者分组,指定同一分组可以消费同一类型的消息,如果没有指定,将会采取默认的分组模式,这里实例化了一个DefaultMQPushConsumerImpl对象,它是后面消费功能的主要实现类。

// 实例化消费者
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("TestConsumer");

主要通过DefaultMQPushConsumer实例化DefaultMQPushConsumerImpl,它是主要的消费功能实现类。

public DefaultMQPushConsumer(final String consumerGroup, RPCHook rpcHook,
       AllocateMessageQueueStrategy allocateMessageQueueStrategy) {
       this.consumerGroup = consumerGroup;
       this.allocateMessageQueueStrategy = allocateMessageQueueStrategy;
       defaultMQPushConsumerImpl = new DefaultMQPushConsumerImpl(this, rpcHook);
   }

2.2 设置NameServer和订阅topic过程

// 设置NameServer的地址
consumer.setNamesrvAddr("localhost:9876");
// 订阅一个或者多个Topic,以及Tag来过滤需要消费的消息
consumer.subscribe("Test", "*");

2.2.1 添加tag

设置NameServer地址后,这个地址为你名字服务集群的地址,类似于zookeeper集群地址,样例给出的是单机本地地址,搭建集群后,可以设置为集群地址,接下来我们需要订阅一个主题topic下的消息,设置对应的topic,可以进行分类,通过设置不同的tag来实现,但目前只支持"||"进行连接,如:"tag1 || tag2 || tag3"。归根在于构造订阅数据时,源码通过"||"进行了字符串的分割,如下所示:

public static SubscriptionData buildSubscriptionData(final String consumerGroup, String topic,
    String subString) throws Exception {
    SubscriptionData subscriptionData = new SubscriptionData();
    subscriptionData.setTopic(topic);
    subscriptionData.setSubString(subString);
    if (null == subString || subString.equals(SubscriptionData.SUB_ALL) || subString.length() == 0) {
        subscriptionData.setSubString(SubscriptionData.SUB_ALL);
    } else {
        String[] tags = subString.split("\\|\\|");
        if (tags.length > 0) {
            for (String tag : tags) {
                if (tag.length() > 0) {
                    String trimString = tag.trim();
                    if (trimString.length() > 0) {
                        subscriptionData.getTagsSet().add(trimString);
                        subscriptionData.getCodeSet().add(trimString.hashCode());
                    }
                }
            }
        } else {
            throw new Exception("subString split error");
        }
    }
    return subscriptionData;
}

2.2.2 发送心跳至Broker

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Spring Boot项目中集成RocketMQ并实现消费者确认,你可以按照以下步骤进行操作: 1. 首先,确保在你的pom.xml文件中引入了RocketMQ的相关依赖项。这可以通过在pom.xml文件中添加以下代码来实现: ``` <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> ``` 这将使你能够在Spring Boot项目中使用RocketMQ的功能。 2. 接下来,你需要在你的Spring Boot应用程序中创建一个消费者类。你可以使用@RocketMQMessageListener注解来标记这个类,并指定要消费的主题和消费者组。在这个类中,你可以编写逻辑来处理接收到的消息。 3. 在消费者类中,你可以使用@RocketMQTransactionListener注解来标记一个用于确认消息的方法。这个方法将在消费者成功处理消息后被调用。你可以在这个方法中进行一些后续处理,比如提交数据库事务等。同时,你还可以在此方法中抛出异常来触发消息回滚。 4. 在消费者类中,你可以使用@RocketMQMessageListener注解中的consumerGroup属性来指定消费者组。这将确保多个消费者在同一组中共享消息的消费进度。这样,只有当所有消费者成功处理消息时,消息才会被标记为已消费,并从RocketMQ服务器中删除。 通过这些步骤,你就可以在Spring Boot项目中集成RocketMQ,并实现消费者确认的功能。请根据你的实际需求和业务逻辑进行相应的配置和处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [SpringBoot集成RocketMQ事务消息](https://blog.csdn.net/ctwy291314/article/details/128659943)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值