为了账号安全,请及时绑定邮箱和手机立即绑定

手写rocketMQ资料:入门级教程详解

标签:
中间件
概述

本文详细介绍了RocketMQ的环境搭建、核心概念解析以及手写代码实践,帮助读者全面了解和使用RocketMQ。文章涵盖了从源码下载、编译到启动的整个环境搭建过程,并深入讲解了RocketMQ的Topic、Tag、Producer、Consumer等核心概念。此外,通过手写代码的方式,演示了消息发送和接收的具体步骤。手写RocketMQ资料将帮助你掌握RocketMQ的使用与配置。

RocketMQ简介
RocketMQ是什么

RocketMQ是由阿里云开发的一款分布式消息中间件,它提供了高性能、高可用、高可靠的消息发布和订阅服务。RocketMQ能够很好地支持大规模分布式系统中消息的传输、异步解耦等需求。在设计上,RocketMQ借鉴了Kafka、RabbitMQ等消息队列的特点,并在性能、可靠性等方面做了优化和改进。

RocketMQ的特点与优势
  1. 高性能:RocketMQ采用了Pull模式,相较于Push模式,这种模式可以更好地管理内存和网络资源,减少资源消耗,提升性能。

  2. 高可用:RocketMQ通过多Broker集群和消息复制机制保证了系统的高可用性。当某个Broker出现故障时,可以自动切换到其他Broker继续提供服务。

  3. 高可靠性:RocketMQ支持消息的顺序发送和消费,保证消息的可靠传输。通过消息幂等性等特性确保消息不会丢失或重复。

  4. 灵活的路由机制:RocketMQ提供了多种路由策略,包括广播模式、集群模式、自定义路由等,可以根据业务需求灵活配置。

  5. 强大的扩展性:RocketMQ支持水平和垂直扩展,可以方便地扩展系统的处理能力和存储能力。
RocketMQ的适用场景
  1. 异步通信:RocketMQ可以实现系统之间的异步解耦,使得各个模块可以独立开发和部署,降低系统之间的耦合度。

  2. 流量削峰填谷:在高并发场景下,可以利用RocketMQ进行削峰填谷,将瞬时的大流量拆分成多个小流量,确保系统稳定运行。

  3. 日志收集与处理:RocketMQ可以用于日志的收集、传输和处理,支持将不同来源的日志汇聚到一个地方进行集中处理。

  4. 数据库同步:RocketMQ可以实现数据库之间的数据同步,支持数据的增量同步,确保数据的一致性和可靠性。
环境搭建
快速搭建RocketMQ环境
  1. 下载RocketMQ源码

    git clone https://github.com/apache/rocketmq.git
    cd rocketmq
  2. 编译RocketMQ源码

    mvn clean install -DskipTests
  3. 启动RocketMQ
    sh bin/mq.cmd start

注意:RocketMQ的启动脚本和命令依赖于操作系统,上述命令适用于Windows环境。在Linux环境下,需要使用sh bin/mq.sh start来启动RocketMQ。

源码下载与编译

下载RocketMQ源码:

git clone https://github.com/apache/rocketmq.git
cd rocketmq

编译RocketMQ源码:

mvn clean install -DskipTests

编译完成后,RocketMQ的编译产物将被放置在distribution/target/apache-rocketmq目录下。

环境配置与启动

环境配置

conf目录下,可以找到RocketMQ的配置文件。可以通过修改这些配置文件来调整RocketMQ的行为,例如修改broker.properties文件中的brokerNamebrokerId等参数。

brokerId=0
brokerName=broker-a

启动RocketMQ

bin目录下,有RocketMQ的启动脚本。在Windows环境下,可以使用mq.cmd脚本;在Linux环境下,可以使用mq.sh脚本。

启动RocketMQ:

# Windows
sh bin/mq.cmd start

# Linux
sh bin/mq.sh start

启动RocketMQ后,可以在日志文件中查看RocketMQ的启动情况。默认的日志文件位于logs目录下。

核心概念解析
Topic与Tag

Topic

在RocketMQ中,Topic是消息的分类标签,用于区分不同类型的业务消息。生产者发送的消息会根据指定的Topic进行分类,消费者则根据订阅的Topic来接收消息。

例如,可以为不同的业务创建不同的Topic:

public static void main(String[] args) throws Exception {
    // 创建Producer实例
    DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
    producer.setNamesrvAddr("localhost:9876");
    producer.start();

    // 发送消息
    Message message = new Message("TopicA", "TagA", "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET));
    SendResult sendResult = producer.send(message);
    System.out.println(sendResult);

    producer.shutdown();
}

Tag

在RocketMQ中,除了Topic外,还可以使用Tag来进一步细分消息。Tag类似于Topic的子分类,可以用来对消息进行更细粒度的标记。

例如,可以在同一个Topic下,为不同的业务创建不同的Tag:

public static void main(String[] args) throws Exception {
    // 创建Producer实例
    DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
    producer.setNamesrvAddr("localhost:9876");
    producer.start();

    // 发送消息
    Message message = new Message("TopicA", "TagB", "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET));
    SendResult sendResult = producer.send(message);
    System.out.println(sendResult);

    producer.shutdown();
}
Producer与Consumer

Producer

生产者(Producer)负责发送消息到RocketMQ。在RocketMQ中,生产者需要首先创建一个DefaultMQProducer实例,并设置相应的参数,例如生产者组名和NameServer地址。

public static void main(String[] args) throws Exception {
    // 创建Producer实例
    DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
    producer.setNamesrvAddr("localhost:9876");
    producer.start();

    // 发送消息
    Message message = new Message("TopicA", "TagA", "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET));
    SendResult sendResult = producer.send(message);
    System.out.println(sendResult);

    producer.shutdown();
}

Consumer

消费者(Consumer)负责从RocketMQ接收并处理消息。在RocketMQ中,消费者需要首先创建一个DefaultMQPushConsumerDefaultMQPullConsumer实例,并设置相应的参数,例如消费者组名、NameServer地址和订阅的主题。

public static void main(String[] args) throws Exception {
    // 创建Consumer实例
    DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
    consumer.setNamesrvAddr("localhost:9876");
    consumer.subscribe("TopicA", "*");

    // 注册消息处理器
    consumer.registerMessageListener((msgs, context) -> {
        for (MessageExt msg : msgs) {
            System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), new String(msg.getBody()));
        }
        return MessageProcess.Result.CONSUME_SUCCESS;
    });

    // 启动Consumer
    consumer.start();
}
Message与Message Queue

Message

消息(Message)是RocketMQ的核心概念之一,它封装了发送者希望传递的数据。每个消息都包含一些基本属性,例如消息体、Topic、Tag、Key等。

消息体

消息体(Body)是消息中实际携带的数据部分,通常是以字节的形式传递。

Message message = new Message("TopicA", "TagA", "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET));

属性

除了消息体外,还可以为消息添加一些额外的属性,例如消息的Key。

Message message = new Message("TopicA", "TagA", "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET));
message.setKeys("uniqueKey");

Message Queue

消息队列(Message Queue)是消息存储的最小单元,每个Topic可以拥有一个或多个消息队列。消息队列的数量决定了消息的并发级别,越多的消息队列可以支持更高的并发处理能力。

创建消息队列

消息队列的创建通常由RocketMQ自动完成,开发人员通常不需要手动创建消息队列。但是,可以通过配置Broker的配置文件来调整消息队列的数量。

brokerId=0
brokerName=broker-a
messageQueueNums=4

上述配置表示该Broker下TopicA有4个消息队列。

消息发送与接收示例

创建Producer发送消息到特定消息队列

public static void main(String[] args) throws Exception {
    DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
    producer.setNamesrvAddr("localhost:9876");
    producer.start();

    Message message = new Message("TopicA", "TagA", "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET));
    SendResult sendResult = producer.send(message);
    System.out.println(sendResult);

    producer.shutdown();
}

创建Consumer接收消息

public static void main(String[] args) throws Exception {
    DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
    consumer.setNamesrvAddr("localhost:9876");
    consumer.subscribe("TopicA", "*");

    consumer.registerMessageListener((msgs, context) -> {
        for (MessageExt msg : msgs) {
            System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), new String(msg.getBody()));
        }
        return MessageProcess.Result.CONSUME_SUCCESS;
    });

    consumer.start();
}
手写代码实践
创建Producer发送消息步骤详解
  1. 创建Producer实例
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
  1. 设置NameServer地址
producer.setNamesrvAddr("localhost:9876");
  1. 启动Producer
producer.start();
  1. 创建消息
Message message = new Message("TopicA", "TagA", "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET));
  1. 发送消息
SendResult sendResult = producer.send(message);
  1. 关闭Producer
producer.shutdown();

创建Producer发送消息的完整代码

public static void main(String[] args) throws Exception {
    // 创建Producer实例
    DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
    producer.setNamesrvAddr("localhost:9876");
    producer.start();

    // 发送消息
    Message message = new Message("TopicA", "TagA", "Hello RocketMQ".getBytes(RemotingHelper.DEFAULT_CHARSET));
    SendResult sendResult = producer.send(message);
    System.out.println(sendResult);

    // 关闭Producer
    producer.shutdown();
}
创建Consumer接收消息步骤详解
  1. 创建Consumer实例
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
  1. 设置NameServer地址
consumer.setNamesrvAddr("localhost:9876");
  1. 订阅Topic
consumer.subscribe("TopicA", "*");
  1. 注册消息处理器
consumer.registerMessageListener((msgs, context) -> {
    for (MessageExt msg : msgs) {
        System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), new String(msg.getBody()));
    }
    return MessageProcess.Result.CONSUME_SUCCESS;
});
  1. 启动Consumer
consumer.start();

创建Consumer接收消息的完整代码

public static void main(String[] args) throws Exception {
    // 创建Consumer实例
    DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
    consumer.setNamesrvAddr("localhost:9876");
    consumer.subscribe("TopicA", "*");

    // 注册消息处理器
    consumer.registerMessageListener((msgs, context) -> {
        for (MessageExt msg : msgs) {
            System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), new String(msg.getBody()));
        }
        return MessageProcess.Result.CONSUME_SUCCESS;
    });

    // 启动Consumer
    consumer.start();
}
消息过滤与路由策略

RocketMQ提供了多种消息过滤和路由策略,可以根据业务需求灵活配置。

消息过滤

可以通过设置消息的Tag来实现消息过滤。例如,消费者只订阅特定Tag的消息,而忽略其他Tag的消息。

consumer.subscribe("TopicA", "TagA");

路由策略

RocketMQ支持多种路由策略,例如广播模式、集群模式等。

广播模式

在广播模式下,消息会被广播到集群中的所有实例。

DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
consumer.setNamesrvAddr("localhost:9876");
consumer.setMessageModel(MessageModel.BROADCASTING);
consumer.subscribe("TopicA", "*");

consumer.registerMessageListener((msgs, context) -> {
    for (MessageExt msg : msgs) {
        System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), new String(msg.getBody()));
    }
    return MessageProcess.Result.CONSUME_SUCCESS;
});

consumer.start();

集群模式

在集群模式下,消息会被路由到集群中的一个实例。

DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
consumer.setNamesrvAddr("localhost:9876");
consumer.setMessageModel(MessageModel.CLUSTERING);
consumer.subscribe("TopicA", "*");

consumer.registerMessageListener((msgs, context) -> {
    for (MessageExt msg : msgs) {
        System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), new String(msg.getBody()));
    }
    return MessageProcess.Result.CONSUME_SUCCESS;
});

consumer.start();
常见问题与解决
遇到的常见问题
  1. 消息发送失败

    如果消息发送失败,可以通过查看Producer的日志来分析原因。通常,日志会显示具体的错误信息,例如网络连接失败、消息队列已满等。

  2. 消费者接收不到消息

    如果消费者接收不到消息,首先检查是否订阅了正确的Topic和Tag。其次,检查消息是否被正确发送到指定的Topic和Tag。

  3. 消息重复

    如果出现消息重复的问题,可以检查消费者的消息处理逻辑是否正确处理了消息的幂等性。

  4. 性能问题

    如果系统性能不佳,可以检查消息队列的数量是否合理,检查网络带宽是否充足,检查系统资源是否紧张。

问题排查与解决技巧
  1. 查看日志

    RocketMQ提供了详细的日志输出,可以通过查看日志来定位问题。日志文件通常位于RocketMQ的安装目录下。

  2. 监控系统

    使用RocketMQ自带的监控工具,可以实时监控系统状态,包括消息的发送和接收情况、系统资源的使用情况等。

  3. 配置优化

    根据实际使用情况,调整RocketMQ的配置参数,例如消息队列的数量、消息的堆积阈值等。

  4. 网络排查

    如果网络连接存在问题,可以使用pingtraceroute等工具来检查网络链路是否通畅。

小结与进阶方向
RocketMQ入门回顾
  • 环境搭建:通过源码下载、编译和启动RocketMQ,完成了环境部署。
  • 核心概念:介绍了RocketMQ中的核心概念,包括Topic、Tag、Producer、Consumer、Message和Message Queue。
  • 代码实践:通过手写代码的方式,实践了消息发送和接收的过程,并介绍了消息过滤和路由策略。
  • 常见问题:总结了RocketMQ中常见的问题及解决方法,包括消息发送失败、接收不到消息、消息重复等问题。
进一步学习的资源推荐
  • 官方文档:RocketMQ的官方文档提供了详细的配置和使用说明,是学习RocketMQ的最佳资源。
  • 慕课网:慕课网提供了多门关于RocketMQ的教程,适合不同层次的学习者。
  • 社区论坛:RocketMQ的社区论坛是一个很好的交流平台,可以在那里找到许多关于RocketMQ的讨论和解决方案。
  • 视频教程:YouTube、B站等视频网站上有许多关于RocketMQ的视频教程,适合喜欢通过视频学习的同学。

通过以上内容的学习,读者可以对RocketMQ有一个全面的了解,并能够熟练地使用RocketMQ进行消息传输和系统解耦。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消