IDEA 导入 RocketMQ 源码

目录

  • 前言
  • [一、RocketMQ 架构](#一、RocketMQ 架构)
  • 二、环境准备
  • 三、下载源码
  • 四、编译源码
    • [4.1 导入源码](#4.1 导入源码)
    • [4.2 目录结构](#4.2 目录结构)
    • [4.3 运行程序](#4.3 运行程序)
      • [1. 启动 Namesrv](#1. 启动 Namesrv)
      • [2. 启动 Broker](#2. 启动 Broker)
      • [3. 启动 Producer](#3. 启动 Producer)
      • [4. 启动 Consumer](#4. 启动 Consumer)
  • 五、监控平台的搭建
    • [5.1 下载 console 源码](#5.1 下载 console 源码)
    • [5.2 IDEA 启动](#5.2 IDEA 启动)

前言

最近项目中有个功能需要在本地调试下 RocketMQ,所以需要在本地导入 RocketMQ 的源码并启动,故做此记录,便于回顾问题和与各位同学一起探讨。


一、RocketMQ 架构

在源码搭建前, 需要先理解 RocketMQ 的四个重要组件, 以及 RocketMQ 的工作流程:

  • NameServer 是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。

  • Broker 部署相对复杂,Broker 分为 MasterSlave,一个 Master 可以对应多个 Slave,但是一个 Slave 只能对应一个 MasterMasterSlave 的对应关系通过指定相同的 BrokerName,不同的 BrokerId 来定义,BrokerId0 表示 Master,非 0 表示 SlaveMaster 也可以部署多个。每个 BrokerNameServer 集群中的所有节点建立长连接,定时注册 Topic 信息到所有 NameServer。 注意:当前 RocketMQ 版本在部署架构上支持一 MasterSlave,但只有 BrokerId=1 的从服务器才会参与消息的读负载。

  • ProducerNameServer 集群中的其中一个节点(随机选择)建立长连接,定期从 NameServer 获取 Topic 路由信息,并向提供 Topic 服务的 Master 建立长连接,且定时向 Master 发送心跳。Producer 完全无状态,可集群部署。

  • ConsumerNameServer 集群中的其中一个节点(随机选择)建立长连接,定期从 NameServer 获取 Topic 路由信息,并向提供 Topic 服务的 MasterSlave 建立长连接,且定时向 MasterSlave 发送心跳。Consumer 既可以从 Master 订阅消息,也可以从 Slave 订阅消息,消费者在向 Master 拉取消息时,Master 服务器会根据拉取偏移量与最大偏移量的距离(判断是否读老消息,产生读 I/O),以及从服务器是否可读等因素建议下一次是从 Master 还是 Slave 拉取。

结合部署架构图,描述集群工作流程:

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

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

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

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

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


二、环境准备

  • ① JDK 1.8

    java -version

  • ② IntelliJ IDEA 2021

  • ③ RocketMQ-4.9.x 源码

  • ④ Maven

  • ⑤ Git

  • ⑥ Windows 11


三、下载源码

我们可以在 github 或者 gitee 上都能下载到 RocketMQ 的源码

github 上下载:

github 上搜素 rocketmq 就能找到:https://github.com/apache/rocketmq

gitee上下载:

gitee 上搜素 rocketmq 就能找到:https://gitee.com/apache/rocketmq

这里我是直接下载 ZIP 压缩包的,可以避免很多问题

解压:


四、编译源码

4.1 导入源码

打开 IDEA ,选择 File -> Open

选中 rocketmq 源码所在目录

导入进来是这样子的

项目导进来之后先检查下 JDK 的配置,配置 JDK 版本 1.8 的(建议 JDK 的版本不要配置太高)

配置你的 Maven

检查下 git 配置(编译的时候会自动去检测 git,所以需要检查下)


4.2 目录结构


4.3 运行程序

本地 Debug 环境搭建过程如下:

  • ① 通过源码启动 Namesrv
  • ② 通过源码启动 broker
  • ③ 通过源码启动 Producer
  • ④ 通过源码启动 Consumer

1. 启动 Namesrv

Namesrv 源码在 rocketmq-namesrv 包下,启动类是 src/main/java/org/apache/rocketmq/namesrv/NamesrvStartup.java,直接通过NamesrvStartupmain 方法启动会失败

终端输出提示我们需要配置一个 ROCKETMQ_HOME 环境变量,我们将环境变量配置到 IDEA

例如:ROCKETMQ_HOME=D:\source-code\rocketmq-4.9.x\rocketmq-4.9.x

再次启动 NamesrvStartup 后再次报错

意思是没有读到 conf 目录下的配置文件 logback_namesrv.xml

那就在项目下创建一个 conf 的文件夹

logback_namesrv.xml 这个配置文件可以在 distribution 的模块下找到,只需要将该文件复制一份到你所创建 conf 目录下即可

再启动 namesrv,控制台提示启动成功 The Name Server boot success.

到此 NameSrver 就算是启动完成了


2. 启动 Broker

Broker 源码在 rocketmq-broker 包下,启动类是 src/main/java/org/apache/rocketmq/broker/BrokerStartup.java,如果直接通过 IDEA 启动也是会失败

与上面 namesrv 一样,我们在 IDEA 上配置启动环境变量 ROCKETMQ_HOME

例如:ROCKETMQ_HOME=D:\source-code\rocketmq-4.9.x\rocketmq-4.9.x

再次启动还是会报与 Nameserv 相同的问题,我们只需要在 distribution 模块下找到 broker 相关的两个配置文件 logback_broker.xmlbroker.conf 两个文件复制到 conf 目录下即可

再次启动,就可以看到 broker 也正常运行了

但是仔细观察会发现虽然 broker 启动成功了,但是 brokerName 好像和配置文件 broker.conf 中的 brokerName 不一致

我们可以启动 broker 时让它指定以 conf/broker.conf 的配置文件启动

再次启动

broker.conf 的配置文件中还有以下配置可以修改

sql 复制代码
# namesrv服务地址
namesrvAddr = 127.0.0.1:9876
# 运行自动创建topic,避免调试的时候麻烦
autoCreateTopicEnable = true
# 数据存储路径
storePathRootDir = D:/file/rocketmq/data_store
# commitlog存储文件
storePathCommitLog = D:/file/rocketmq/data_store/commitlog
# 消费队列存储文件
storePathConsumeQueue = D:/file/rocketmq/data_store/consumequeue
# 索引存储文件
storePathIndex = D:/file/rocketmq/data_store/index
# checkpoint存储文件
storeCheckpoint = D:/file/rocketmq/data_store/checkpoint
# abort文件
abortFile = D:/file/rocketmq/data_store/abort

做本地调试的时候最好添加以下两个配置:

sql 复制代码
# namesrv服务地址
namesrvAddr = 127.0.0.1:9876
# 运行自动创建topic,避免调试的时候麻烦
autoCreateTopicEnable = true

为了更好的查看启动 broker 的相关配置,可以在 logback_broker.xml 配置文件中的 RocketmqBroker 里面追加 <appender-ref ref="STDOUT"/> 配置,例如:

xml 复制代码
    <logger name="RocketmqBroker" additivity="false">
        <level value="INFO"/>
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="RocketmqBrokerAppender"/>
    </logger>

3. 启动 Producer

example 模块中官方给了一个 producer 的示例

sql 复制代码
package org.apache.rocketmq.example.quickstart;

import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;

public class Producer {

	// 发送消息次数:原本是 1000 次,作为演示我调整为 1 次
    public static final int MESSAGE_COUNT = 1;
    public static final String PRODUCER_GROUP = "please_rename_unique_group_name";
    public static final String DEFAULT_NAMESRVADDR = "127.0.0.1:9876";
    public static final String TOPIC = "TopicTest";
    public static final String TAG = "TagA";

    public static void main(String[] args) throws MQClientException, InterruptedException {

        DefaultMQProducer producer = new DefaultMQProducer(PRODUCER_GROUP);
        // 下面这行代码原本是注释的,这里要放开注释
        producer.setNamesrvAddr(DEFAULT_NAMESRVADDR);

        producer.start();

        for (int i = 0; i < MESSAGE_COUNT; i++) {
            try {
                Message msg = new Message(TOPIC /* Topic */,
                    TAG /* Tag */,
                    ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
                );

                SendResult sendResult = producer.send(msg);
                System.out.printf("%s%n", sendResult);
            } catch (Exception e) {
                e.printStackTrace();
                Thread.sleep(1000);
            }
        }
        producer.shutdown();
    }
}

直接运行即可

可以看到是有发送一条消息的


4. 启动 Consumer

同样的在 example 模块中官方给了一个 consumer 的示例

sql 复制代码
package org.apache.rocketmq.example.quickstart;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;

public class Consumer {

    public static final String CONSUMER_GROUP = "please_rename_unique_group_name_4";
    public static final String DEFAULT_NAMESRVADDR = "127.0.0.1:9876";
    public static final String TOPIC = "TopicTest";

    public static void main(String[] args) throws InterruptedException, MQClientException {

        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(CONSUMER_GROUP);
		// 下面这行代码原本是注释的,这里要放开注释
        consumer.setNamesrvAddr(DEFAULT_NAMESRVADDR);

        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        consumer.subscribe(TOPIC, "*");
        consumer.registerMessageListener((MessageListenerConcurrently) (msg, context) -> {
            System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msg);
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        });
        consumer.start();

        System.out.printf("Consumer Started.%n");
    }
}

直接运行

运行后可以看到 consumer 消费调了之前 producer 生成出来的那条消息


五、监控平台的搭建

RocketMQ 有一个专门的监控平台来查看 MQ 的情况,大概长这样子

5.1 下载 console 源码

下载链接:https://github.com/apache/rocketmq-externals

可以通过 git 把它给拉下来,可以看到这里面有 rocketmq 与各种各样的技术集成,但是这个监控平台只需要启动 rocketmq-console 这个服务就行了

以下是我下载的:

链接:百度网盘链接

提取码:no5x

找个目录存放,然后解压下来。

5.2 IDEA 启动

进入 IDEA ,打开 rocketmq-console 项目

IDEA 打开以后,修改配置文件 application.properties

主要是将 rocketmq.config.namesrvAddr 设置成你 RocketMQ 所运行的服务器 IP (公网)地址,然后就可以直接启动了

启动完成之后游览器上输入:localhost:8080,访问

到目前位置,RocketMQ 的监控平台也用 IDEA 启动成功了


参考文章:

RocketMQ 监控平台搭建与项目引入:https://blog.csdn.net/xhmico/article/details/124489116

基于 IDEA 搭建 RocketMQ-4.6 源码环境:https://juejin.cn/post/7166279522772320286

【RocketMQ | 源码分析】RocketMQ本地调试环境搭建:https://juejin.cn/post/7216729116690694199

手把手教你使用Idea调试RocketMQ源码:https://juejin.cn/post/7166175844145037319

RocketMQ 源码分析: https://gitee.com/haijun1998/rocketmqhttps://gitee.com/wen-zhan/rocketmq

相关推荐
customer087 小时前
【开源免费】基于SpringBoot+Vue.JS在线视频教育平台(JAVA毕业设计)
java·jvm·vue.js·spring boot·spring cloud·java-ee·intellij-idea
有邪10 小时前
一文讲懂IDEA的编码格式file encoding
java·ide·intellij-idea
海海不掉头发10 小时前
使用Idea新建一个Demo项目基于WebApp目录下的服务器访问测试-作业篇
服务器·intellij-idea·web app
九转编程蛊10 小时前
idear导入他人项目如何快速运行
intellij-idea
艾伦~耶格尔15 小时前
Java集成开发环境(IDE)之 => “IntelliJ IDEA“ 安装
java·开发语言·intellij-idea
今年不养猪只除草19 小时前
RuoYi-Vue若依框架-系统监控内定时任务的使用
后端·intellij-idea
程序员阿鹏1 天前
final、finally、finalize的区别
java·开发语言·后端·eclipse·intellij-idea
月轩居士1 天前
idea 2024.2切换到旧版的UI
java·ui·intellij-idea
为美好的生活献上中指1 天前
Java学习Day37:HTML 第六章:黄金国(项目思路梳理)
java·开发语言·学习·tomcat·html·maven·intellij-idea
你可以自己看1 天前
编写代码的实用工具
java·intellij-idea