RocketMQ源码解析(搭建环境)

1.读源码前必备

不管是读哪个开源项目的源码,在这之前我们都需要能够知道它是个什么东西,它都有哪些功能,还要熟练的使用它,最好知道它的一些实现原理,这样就能从源码中找到这些原理的影子。

1.1 读源码的勇气与毅力

dubbo应该是我第一个正式阅读源码的框架,我还清晰的记得,当时阅读的时候,看着dubbo项目的那堆子项目就害怕,就感觉那么多什么时候看完,然后读源码的时候又无处下手,因为看不懂嘛,看一小段代码就感觉到胸闷,不过还是坚持过来了,现在想想还是挺有意思的,阅读源码也并没有那么难,难的是坚持,是面对它的勇气,时间就摆在这,你干不干它都在走,如果当时我没有坚持下来,到现在估计也是一无所获,庆幸自己坚持下来了,虽然没有收获什么,但是我不在惧怕阅读源码,只要拿出时间跟它慢慢磨,早晚能够给你磨透,这也是成语铁杵成针的解释。

1.2 关于MQ的理解

我们要阅读RocketMQ的源码,这里你就需要知道什么是MQ,然后MQ有什么作用,像什么解藕,削峰等等(它的作用其实都是需要在项目中慢慢体会的),以及MQ都分为哪几部分,它们的工作过程,工作原理是怎样的。

1.3 RocketMQ架构

像我们普通的MQ中间件,大体上就是三部分组成的,消息生产者,消息中间件,消息消费者。
在这里插入图片描述
首先是消息生产者,产生消息,然后将产生的消息 给 MQ消息中间件,然后MQ把这个消息存起来,然后这个消息消费者就去找MQ消息中间件要消息进行消费。
RocketMQ 它把MQ这个分成了2部分,一个是broker,一个是nameserv,这个broker干的活就是接收 消息生产者 生产的消息,然后将消息存储起来,同时把消息给消息消费者进行消费(这里这个给是抽象的,实际上消费者自己去找broker要的)在RocketMQ中,broker是可以部署多个的,为了保证broker不间断的提供服务,也就是保证它的高可用性,还可以配置主从模式,也就是一主多从
在这里插入图片描述
为了提高MQ的并发性与吞吐量,还可以同种类型的消息(topic),分别存储在不同的broker上面,这样就是多主broker了,然后每个broker下面挂2个从的broker。
在这里插入图片描述
这个nameserv 可以看作一个注册中心或者是路由的东西,因为有很多broker,我们消息生产者与消息消费者想要知道不同的topic在哪些broker上面,我们就需要有个路由的东西告诉它们 ,这个东西就是nameserv,它维护这topic的路由信息,同时,我们要保证nameserv的高可用,也可以部署多个nameserv。
在这里插入图片描述

2.环境搭建

RocketMQ是JAVA语言写的,这对于JAVA开发的同学是非常友好的。

2.1从github上面拉项目

我们先要将RocketMQ的源码从github上面拉到我们自己电脑上面,RocketMQ 源码地址:github。其实最好是将项目fork到你自己的git仓库中,然后再从你自己git仓库中拉下来,这样你写了注释啥的就可以提交上去保存起来。

2.2 导入到idea

导入到idea中,因为是maven项目,所以导入RocketMQ就跟导入其他java maven没有区别,这里就不再赘述。
下图为我导入的RocketMQ源码包结构,其中红框框出来的就是我们上面架构图里面的broker, nameserv,与消息生产者,消息消费者源码包。
在这里插入图片描述
这里面broker 与 nameserv是可以直接用里面的main 方法直接启动的(我们配置完是可以的,他这里面需要配置一个ROCKETMQ_HOME),然后消息生产者与消息消费者 这两个角色需要另起项目,然后maven中引入client的坐标(其实上图目录中有个example子项目,里面有很多RocketMQ使用的案例,我们可以直接使用里面的生产者与消费者源码进行改造,这样就不需要自己再建项目了)

2.3 配置broker

首先你要在你电脑硬盘上选个地作为 ROCKETMQ_HOME,在idea启动参数中配置好。
在这里插入图片描述
在ROCKETMQ_HOME 目录下面创建一个conf的目录,并且创建logback_broker.xml 文件作为broker日志配置文件,这个是RocketMQ broker源代码写死的
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="DefaultAppender"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>你自己的路径/rocketmqlogs/broker_default.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <fileNamePattern>你自己的路径/rocketmqlogs/otherdays/broker_default.%i.log
            </fileNamePattern>
            <minIndex>1</minIndex>
            <maxIndex>5</maxIndex>
        </rollingPolicy>
        <triggeringPolicy
                class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <maxFileSize>100MB</maxFileSize>
        </triggeringPolicy>
        <encoder>
            <pattern>%d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>

    <appender name="RocketmqNamesrvAppender"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>你自己的路径/rocketmqlogs/broker.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <fileNamePattern>你自己的路径/rocketmqlogs/otherdays/broker.%i.log
            </fileNamePattern>
            <minIndex>1</minIndex>
            <maxIndex>5</maxIndex>
        </rollingPolicy>
        <triggeringPolicy
                class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <maxFileSize>100MB</maxFileSize>
        </triggeringPolicy>
        <encoder>
            <pattern>%d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <append>true</append>
        <encoder>
            <pattern>%d{yyy-MM-dd HH\:mm\:ss,SSS} %p %t - %m%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>

    <logger name="RocketmqNamesrv" additivity="false">
        <level value="INFO" />
        <appender-ref ref="RocketmqNamesrvAppender" />
    </logger>

    <logger name="RocketmqCommon" additivity="false">
        <level value="INFO" />
        <appender-ref ref="RocketmqNamesrvAppender" />
    </logger>

    <logger name="RocketmqRemoting" additivity="false">
        <level value="INFO" />
        <appender-ref ref="RocketmqNamesrvAppender" />
    </logger>

    <root>
        <level value="INFO" />
        <appender-ref ref="DefaultAppender" />
    </root>
</configuration>

完成上面这步,我们就把日志相关的配置好了,接下来我们就需要对broker进行配置一下了,这里我提供了一个broker的配置类:

#所属集群名字
brokerClusterName=rocketmq-cluster
#broker名字,注意此处不同的配置文件填写的不一样
brokerName=broker-a
#0 表示 Master,>0 表示 Slave
brokerId=0
#nameServer地址,分号分割
namesrvAddr=127.0.0.1:9876
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许 Broker 自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许 Broker 自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#Broker 对外服务的监听端口
listenPort=10911
#删除文件时间点,默认凌晨 4点
deleteWhen=04
#文件保留时间,默认 48 小时
fileReservedTime=120
#commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30W条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/Users/mac/Desktop/rocketmq/rocketmq/broker/src/conf/store
#commitLog 存储路径
storePathCommitLog=/Users/mac/Desktop/rocketmq/rocketmq/broker/src/conf/commitlog
#消费队列存储路径存储路径
storePathConsumeQueue=/Users/mac/Desktop/rocketmq/rocketmq/broker/src/conf/store/consumequeue
#消息索引存储路径
storePathIndex=/Users/mac/Desktop/rocketmq/rocketmq/broker/src/conf/store/index
#checkpoint 文件存储路径
storeCheckpoint=/Users/mac/Desktop/rocketmq/rocketmq/broker/src/conf/checkpoint
#abort 文件存储路径
abortFile=/Users/mac/Desktop/rocketmq/rocketmq/broker/src/conf/abort
#限制的消息大小
maxMessageSize=65536

#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000

#Broker 的角色
#- ASYNC_MASTER 异步复制Master
#- SYNC_MASTER 同步双写Master
#- SLAVE
brokerRole=ASYNC_MASTER

#刷盘方式
#- ASYNC_FLUSH 异步刷盘
#- SYNC_FLUSH 同步刷盘
flushDiskType=ASYNC_FLUSH
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128

找个地方保存成一个properties文件,接下来我们需要改下源代码了(野路子):找到broker的启动类: org.apache.rocketmq.broker.BrokerStartup 在124 行左右 有这么一段代码:if (commandLine.hasOption('c')) 这个就是判断你启动的时候有没有-c参数,-c参数也就是configfile,指定一个配置文件的地址,也就是当有-c 参数值的时候才会去解析找出这个配置文件并解析,咱们这里把这个判断-c参数的if语句注释掉,然后把后面获取配置文件路径的那行咱们也注释掉,自己加上一个file String变量,这个file变量就是咱们上面properties文件的位置:
在这里插入图片描述

2.4 配置nameserv

其实配置nameserv跟上面配置broker差不多,也是需要在启动参数中指明ROCKETMQ_HOME
在这里插入图片描述
接着就是在这个ROCKETMQ_HOME 目录下面创建 conf 目录,并且创建 logback_namesrv.xml 日志配置文件,这个文件路径与文件名都是RocketMQ写死的。这个logback_namesrv.xml日志文件与上面broker 的那个差不多,改改里面的路径就可以了。
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="DefaultAppender"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>自己路径/rocketmqlogs/namesrv_default.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <fileNamePattern>自己路径/rocketmqlogs/otherdays/namesrv_default.%i.log
            </fileNamePattern>
            <minIndex>1</minIndex>
            <maxIndex>5</maxIndex>
        </rollingPolicy>
        <triggeringPolicy
                class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <maxFileSize>100MB</maxFileSize>
        </triggeringPolicy>
        <encoder>
            <pattern>%d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>

    <appender name="RocketmqNamesrvAppender"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>自己路径/rocketmqlogs/namesrv.log</file>
        <append>true</append>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <fileNamePattern>自己路径/rocketmqlogs/otherdays/namesrv.%i.log
            </fileNamePattern>
            <minIndex>1</minIndex>
            <maxIndex>5</maxIndex>
        </rollingPolicy>
        <triggeringPolicy
                class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <maxFileSize>100MB</maxFileSize>
        </triggeringPolicy>
        <encoder>
            <pattern>%d{yyy-MM-dd HH:mm:ss,GMT+8} %p %t - %m%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <append>true</append>
        <encoder>
            <pattern>%d{yyy-MM-dd HH\:mm\:ss,SSS} %p %t - %m%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>

    <logger name="RocketmqNamesrv" additivity="false">
        <level value="INFO" />
        <appender-ref ref="RocketmqNamesrvAppender" />
    </logger>

    <logger name="RocketmqCommon" additivity="false">
        <level value="INFO" />
        <appender-ref ref="RocketmqNamesrvAppender" />
    </logger>

    <logger name="RocketmqRemoting" additivity="false">
        <level value="INFO" />
        <appender-ref ref="RocketmqNamesrvAppender" />
    </logger>

    <root>
        <level value="INFO" />
        <appender-ref ref="DefaultAppender" />
    </root>
</configuration>

2.5 启动

配置完了上面那几步,就可以启动了,先启动nameserv ,然后再启动 broker, 之后我们可以起example中找个生产者,消费者的例子启动,这里我选择了quickstart里面的消息消费者与消息生产者,分别启动里面的消息消费者与消息生产者。就可以在控制台上面看到消息生产者成功发送消息打印的信息与消息消费者获取到的消息了。

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页