RocketMQ原理、使用与实践指南

  1. 一、RocketMQ 使用方式

    (一)依赖
    在使用 RocketMQ 的 Java 项目中,通常需要添加以下 Maven 依赖:

    <dependency>
        <groupId>org.apache.rocketmq</groupId>
        <artifactId>rocketmq-client</artifactId>
        <version>4.9.3</version>
    </dependency>
    

    请根据实际情况选择合适的 RocketMQ 版本。

    (二)配置

    1. NameServer 地址配置:

      • 在生产者和消费者的代码中,都需要设置 NameServer 的地址,如示例代码中:
      producer.setNamesrvAddr("localhost:9876");
      consumer.setNamesrvAddr("localhost:9876");
      

      这里将 NameServer 地址设置为 localhost:9876,实际应用中需根据你的 NameServer 部署位置进行修改。可以是一个 IP 地址加端口的组合,也可以是多个 NameServer 地址的集合,多个地址之间用分号分隔,以提高系统的可用性,例如:

      producer.setNamesrvAddr("192.168.1.100:9876;192.168.1.101:9876");
      

      这样生产者或消费者会尝试连接这些 NameServer 中的一个,若其中一个不可用,可连接其他的。

    2. 生产者配置:

      • 生产者组名:在创建生产者实例时,需要指定生产者组名,如:
      DefaultMQProducer producer = new DefaultMQProducer("producer - group");
      

      生产者组名用于对生产者进行逻辑分组,方便管理和负载均衡等操作。不同生产者组可以有不同的消息发送策略或行为,可根据业务模块或功能划分生产者组。

      • 消息发送方式配置
        生产者支持同步、异步和单向发送消息。
      // 同步发送
      SendResult sendResult = producer.send(message);
      // 异步发送
      producer.send(message, new SendCallback() {
          @Override
          public void onSuccess(SendResult sendResult) {
              // 消息发送成功后的处理逻辑
          }
          @Override
          public void onException(Throwable e) {
              // 消息发送失败后的处理逻辑
          }
      });
      // 单向发送
      producer.sendOneway(message);
      

      同步发送需要等待接收方响应,适用于重要消息;异步发送可指定回调函数,在发送完成后执行相应操作,适用于对时间敏感场景;单向发送不等待回应,适用于对可靠性要求不高的场景。

      • 消息属性配置
        除了主题和 Tag 外,消息可以设置更多属性,例如消息的键值对:
      message.putUserProperty("key1", "value1");
      

      这些属性可在消费者端根据需要获取,用于业务逻辑的进一步处理。

    3. 消费者配置:

      • 消费者组名:创建消费者实例时指定消费者组名,如:
      DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer - group");
      

      消费者组内的多个消费者会共同处理消息,在集群消费模式下,消息只会被组内一个消费者消费,避免重复消费;在广播消费模式下,组内所有消费者都能收到消息。

      • 消息订阅配置
        可通过 consumer.subscribe 方法订阅主题和 Tag,如:
      consumer.subscribe("TopicTest", "TagA || TagB");
      

      这里订阅了 TopicTest 主题,且包含 TagATagB 的消息,可根据业务需求灵活设置订阅条件。

      • 消费模式配置
        支持集群消费和广播消费,默认为集群消费,可通过以下方式设置为广播消费:
      consumer.setMessageModel(MessageModel.BROADCAST);
      
      • 消息监听器配置
        注册消息监听器,如示例代码中使用的 MessageListenerConcurrently 是并发消费监听器,也可以使用 MessageListenerOrderly 实现顺序消费,其 consumeMessage 方法会确保同一队列的消息顺序消费:
      consumer.registerMessageListener(new MessageListenerOrderly() {
          @Override
          public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
              // 顺序消费的处理逻辑
              return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
          }
      });
      

      消费监听器处理接收到的消息,根据消费结果返回不同状态,如 CONSUME_SUCCESS 表示消费成功,其他状态会触发不同的重试机制。

    二、RocketMQ 概念解释

    (一)核心组件

    1. NameServer:
      • 作为元数据管理中心,主要负责对元数据的管理,包括 Topic 和路由信息的管理。它由 Netty 实现,是无状态节点,提供路由注册、发现和管理服务。类似于 ZooKeeper,但有自身特点。
      • 多个 NameServer 节点组成集群时,相互独立,无信息交互,属于伪集群,这增强了扩展性和稳定性。
      • 主要开销在于维持心跳和提供 Topic - Broker 的对应关系,需要注意心跳数据量问题,若 Topic 过多可能导致心跳失败。
      • 生产者和消费者通过向 NameServer 获取 Broker 的路由信息进行消息发送和拉取操作。
    2. Broker:
      • 是消息的中转站,负责消息的收发和持久化,是 RocketMQ 的核心服务提供方。
      • 与所有 NameServer 节点保持长连接和心跳,将 Topic 信息注册到 NameServer 并更新心跳时间。
      • 提供消息的接收、存储和拉取等功能,支持主从架构(Master - Slave),Master 节点挂掉后,Consumer 可切换到 Slave 节点继续消费消息。
    3. Producer:
      • 是消息的生产者,一般由业务系统产生消息。
      • 与 NameServer 建立连接获取 Topic 路由信息,支持集群部署,可采用不同的消息发送方式(同步、异步、单向)。
      • 不同发送方式适用于不同业务场景,如同步用于重要数据传输,异步用于时间敏感业务,单向用于可靠性要求不高的场景。
    4. Consumer:
      • 是消息的消费者,由业务系统异步消费消息。
      • 支持集群消费和广播消费模式,还支持 Push 和 Pull 两种消费模式,Push 是对 Pull 消费的封装,通过注册消费监听器来实现消息消费。

    (二)核心概念

    1. Message:
      • 消息实体,包含主题(topic)和 Tag 等信息,topic 是消息传输的通道地址,必须设置;Tag 可作为 topic 的子级别,用于更精细标识消息,可根据业务场景灵活设置或不设置。
      • 消息发送方根据 topic 发送消息,消费方根据 topic 选择消费逻辑,Tag 可辅助查找和区分消息,方便业务逻辑的细化处理。
    2. Topic:
      • 消息的主题,属于消息的第一级分类,多个生产者可向同一 Topic 发送消息,多个消费者可同时消费同一 Topic 的消息,实现了生产者和消费者的解耦。
      • 例如在电商系统中,可将所有订单相关消息发送到同一 Topic,不同业务模块可根据需求订阅该 Topic 进行消息获取。
    3. Tag:
      • 属于消息的第二级分类,可看作子主题,为消息提供更多灵活配置,辅助消息的标识和查找。
      • 在同一业务模块中,可通过不同的 Tag 区分不同状态或类型的消息,例如订单业务中的不同订单状态。
    4. Queue 队列:
      • 每个 Queue 内部是有序的,有读写队列之分,与常见读写分离机制不同,保障消息的有序处理和高效读写。
      • 读写队列在数据存储和处理上有独特机制,为消息存储和处理提供了有序环境。
    5. Offset 偏移量:
      • 用于定位消息队列中的消息,是 long 类型,可将消息队列看作无限长的数组,offset 是数组的下标。
      • 通过 offset,消费者能准确找到消息队列中的消息进行消费,确保消息消费的准确性。
    6. Group 分组:
      • 分为生产者组和消费者组,代表一类生产者和消费者,方便对消息的生产和消费进行统一管理和配置。
      • 例如将处理同一业务的生产者或消费者分别划分为一个组,便于进行统一操作和资源分配。

    三、RocketMQ 优缺点总结

    (一)优点

    1. 单机吞吐量:单机可达十万级吞吐量,处理高并发消息能力强,适合大型系统。
    2. 可用性:分布式架构,部分节点故障不影响系统正常运行,保障业务连续性。
    3. 消息可靠性:合理配置可实现近乎 0 丢失,适用于对数据可靠性要求高的领域。
    4. 功能支持:功能完善,提供事务消息、顺序消息等多种特性,扩展性好,便于集群扩展。
    5. 消息堆积能力:支持 10 亿级消息堆积,高负载下性能稳定。
    6. 源码可定制性:基于 Java 开发,方便开发人员定制化开发,对 MQ 掌控度高。
    7. 场景适用性:专为金融互联网领域设计,在高并发场景下表现卓越,经过多次大型促销活动考验。

    (二)缺点

    1. 客户端语言支持有限:目前仅支持 Java 及 C++ 客户端,且 C++ 客户端不成熟,限制多语言开发环境应用。
    2. 社区活跃度:相比热门开源项目,社区活跃度不高,获取支持和解决方案较慢。
    3. 接口兼容性:未实现 JMS 等标准接口,迁移时可能需修改大量代码,增加迁移成本。

    四、RocketMQ 执行流程说明

    1. NameServer 启动:作为路由管理中心首先启动,为后续组件提供服务。
    2. Broker 注册:Broker 启动时向 NameServer 注册自身信息,包括地址和负责的 Topic 等。
    3. 生产者发送消息:生产者从 NameServer 获取 Broker 服务器地址列表,根据负载均衡算法选择 Broker 发送消息,避免单点压力过大。
    4. NameServer 与 Broker 心跳检测:NameServer 与 Broker 维持心跳机制,检测 Broker 是否存活,若宕机将其从路由表移除,确保路由信息准确。
    5. 消费者订阅消息:消费者从 NameServer 获取 Broker 地址列表,根据 Broker 配置决定订阅消息规则,可配置不同消费策略。

    五、RocketMQ 中 Broker 故障处理机制

    1. Broker 与 NameServer 之间每隔 30s 进行心跳连接,NameServer 每隔 10s 检查 Broker 心跳时间,超过 120s 无心跳则认为 Broker 挂掉。
    2. 对于生产者,通过负载均衡算法避免向故障 Broker 发送消息,将消息改发到正常 Broker 上。
    3. 对于消费者,可从 Broker 的 Slave 节点拉取消息继续消费,保证系统可用性和数据连续性。

    六、示例代码解释

    (一)生产者代码

    public class ProducerExample {
        public static void main(String[] args) throws Exception {
            // 创建一个生产者实例,并指定生产者组名
            DefaultMQProducer producer = new DefaultMQProducer("producer - group");
            // 设置NameServer地址
            producer.setNamesrvAddr("localhost:9876");
            // 启动生产者
            producer.start();
    
            for (int i = 0; i < 10; i++) {
                // 创建一条消息,指定主题、Tag和消息内容
                Message message = new Message("TopicTest", "TagA", ("Hello RocketMQ " + i).getBytes());
                // 同步发送消息
                SendResult sendResult = producer.send(message);
                System.out.printf("%s%n", sendResult);
            }
    
            // 关闭生产者
            producer.shutdown();
        }
    }
    

    这段代码实现了一个简单的 RocketMQ 生产者。首先导入相关类,创建 DefaultMQProducer 实例并指定生产者组名,设置 NameServer 地址,启动生产者。通过循环创建 10 条消息,指定主题和 Tag,使用同步发送方式发送消息,打印发送结果,最后关闭生产者。

    (二)消费者代码

    public class ConsumerExample {
        public static void main(String[] args) throws Exception {
            // 创建一个消费者实例,并指定消费者组名
            DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer - group");
            // 设置NameServer地址
            consumer.setNamesrvAddr("localhost:9876");
            // 订阅主题和Tag
            consumer.subscribe("TopicTest", "TagA");
    
            // 注册消息监听器,用于处理接收到的消息
            consumer.registerMessageListener(new MessageListenerConcurrently() {
                @Override
                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                    for (MessageExt msg : msgs) {
                        System.out.println(new String(msg.getBody()));
                    }
                    // 返回消费成功状态
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
            });
    
            // 启动消费者
            consumer.start();
            System.out.println("Consumer Started.");
        }
    }
    

    该代码实现了一个简单的 RocketMQ 消费者。导入相关类后,创建 DefaultMQPushConsumer 实例,指定消费者组名,设置 NameServer 地址,订阅主题和 Tag,注册并发消息监听器处理消息,将消息内容打印输出,返回消费成功状态,最后启动消费者并输出启动信息。

    七、总结

    RocketMQ 是一款由阿里巴巴自主研发的高性能消息中间件,具有分布式架构、高吞吐量、高可用性和高可靠性等诸多优点,在消息类型、功能支持和消息堆积能力上表现出色,尤其适用于金融、电商等对数据可靠性和高并发处理要求较高的领域。然而,它也存在一些局限性,如客户端语言支持不够丰富,社区活跃度相对较低,以及接口兼容性方面的问题。通过其核心组件(NameServer、Broker、Producer 和 Consumer)的协同工作,以及对核心概念(Message、Topic、Tag、Queue、Offset 和 Group)的巧妙运用,RocketMQ 能够实现高效的消息传输和处理。在实际使用中,开发者需要根据业务需求合理配置生产者和消费者,选择合适的消息发送和消费模式,同时要关注 NameServer 与 Broker 的心跳机制和故障处理,确保系统的稳定运行。示例代码展示了简单的生产者和消费者的实现,为开发人员提供了一个入门的参考,帮助他们更好地理解和使用 RocketMQ 进行消息的生产和消费操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白的一叶扁舟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值