1. 基本架构
RocketMQ架构上主要分为四部分,如下图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/6bd9105790155f21f67db36f54ba413e.png)
Producer:消息发布的角色,支持分布式集群方式部署。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。
Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。
NameServer:NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:
Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活;
路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。
NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Producer,Consumer仍然可以动态感知Broker的路由的信息。
BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证,为了实现这些功能,Broker包含了以下几个重要子模块:
Remoting Module:整个Broker的实体,负责处理来自clients端的请求。
Client Manager:负责管理客户端(Producer/Consumer)和维护Consumer的Topic订阅信息
Store Service:提供方便简单的API接口处理消息存储到物理硬盘和查询功能。
HA Service:高可用服务,提供Master Broker 和 Slave Broker之间的数据同步功能。
Index Service:根据特定的Message key对投递到Broker的消息进行索引服务,以提供消息的快速查询。
![](https://i-blog.csdnimg.cn/blog_migrate/64c4f52432e85d6453da125aae06b990.png)
2. 获取源码
rocketMq项目的github仓库为github.com/apache/rock…。 我们选择4.8版本。
3. 本地启动
拿到代码后,我们就开始进行本地启动了,没错,就是在idea中进行启动。
3.1 复制conf目录
在启动项目前,我们需要进行一些配置,rocketMq项目的配置文件位于rocketmq/distribution模块下的conf目录中,直接整个复制到某个目录下(作为rocketmq的根目录,存放conf,log,store等内容):
![](https://i-blog.csdnimg.cn/blog_migrate/4e6649285e2df48ae293fee85f1371b6.png)
也不需要改动,复制出来就行了,这些配置的内容后面分析源码时再讲解吧。
3.2 启动nameServer
nameServer的主类为org.apache.rocketmq.namesrv.NamesrvStartup:
![](https://i-blog.csdnimg.cn/blog_migrate/520aabb21a4698031508f1fb277a2878.png)
如果我们直接运行main()方法,会报错:
![](https://i-blog.csdnimg.cn/blog_migrate/35e609b03326d5006c32672337b87bce.png)
报错信息已经很明确了,需要我们配置ROCKETMQ_HOME目录,我们在idea中进行配置即可:
打开配置界面,填写ROCKETMQ_HOME配置:
![](https://i-blog.csdnimg.cn/blog_migrate/80a2cd3c870c8540cb4e4867b346d078.png)
这里我填写的是ROCKETMQ_HOME=/Users/haoshaofei/IdeaProjects/rocketmq-home,这个ROCKETMQ_HOME路径就是conf文件夹所在的目录。
填写好后,就可以启动了:
![](https://i-blog.csdnimg.cn/blog_migrate/498635233b25693789770a95cb728dbe.png)
3.3 启动broker
broker的主类为org.apache.rocketmq.broker.BrokerStartup,启动方式与nameServer很相似,启动前也要配置ROCKETMQ_HOME路径:
![](https://i-blog.csdnimg.cn/blog_migrate/198d9f1b477a1a9297fe65ed85b6ef19.png)
相比于nameServer,这里多需要指定配置文件conf:
#所属集群名字brokerClusterName=rocketmq-cluster
#broker名字,注意此处不同的配置文件填写的不一样brokerName=broker-a
#0 表示 Master,>0 表示 SlavebrokerId=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每个文件的大小默认1GmapedFileSizeCommitLog=1073741824#ConsumeQueue每个文件默认存30W条,根据业务情况调整mapedFileSizeConsumeQueue=300000#destroyMapedFileIntervalForcibly=120000#redeleteHangedFileInterval=120000#检测物理文件磁盘空间diskMaxUsedSpaceRatio=88#存储路径storePathRootDir=/Users/haoshaofei/IdeaProjects/rocketmq-home/store
#commitLog 存储路径storePathCommitLog=/Users/haoshaofei/IdeaProjects/rocketmq-home/store/commitlog
#消费队列存储路径存储路径storePathConsumeQueue=/Users/haoshaofei/IdeaProjects/rocketmq-home/store/consumequeue
#消息索引存储路径storePathIndex=/Users/haoshaofei/IdeaProjects/rocketmq-home/store/index
#checkpoint 文件存储路径storeCheckpoint=/Users/haoshaofei/IdeaProjects/rocketmq-home/checkpoint
#abort 文件存储路径abortFile=/Users/haoshaofei/IdeaProjects/rocketmq-home/abort
#限制的消息大小maxMessageSize=65536#flushCommitLogLeastPages=4#flushConsumeQueueLeastPages=2#flushCommitLogThoroughInterval=10000#flushConsumeQueueThoroughInterval=60000#Broker 的角色#- ASYNC_MASTER 异步复制Master#- SYNC_MASTER 同步双写Master#- SLAVEbrokerRole=ASYNC_MASTER
#刷盘方式#- ASYNC_FLUSH 异步刷盘#- SYNC_FLUSH 同步刷盘flushDiskType=ASYNC_FLUSH
#checkTransactionMessageEnable=false#发消息线程池数量#sendMessageThreadPoolNums=128#拉消息线程池数量#pullMessageThreadPoolNums=128复制代码
添加启动参数:
![](https://i-blog.csdnimg.cn/blog_migrate/8be1ea39ec43dc910f6fea204b3e37f7.png)
配置完成之后就可以启动了:
![](https://i-blog.csdnimg.cn/blog_migrate/e982a58e63bd605fcaf8d51e5bdf9e46.png)
3.4 启动管理后台
rocketMq的管理后台在另一个仓库github.com/apache/rock…,除了后台,这个仓库还包含了许多的其他模块:
![](https://i-blog.csdnimg.cn/blog_migrate/64a263245894f7ede1733b5ca0f6450b.png)
我们并不需要分析这个项目,源码本可以不必下载,但我在找这个项目的release版本时,发现并没有提供已编译好的jar包,需要自己构建代码,因此我就再次下载了这个代码源码。
这个项目的代码我们并不分析,因此直接在master分支上操作即可,
管理后台项目为rocketmq-console,主类为org.apache.rocketmq.console.App:
![](https://i-blog.csdnimg.cn/blog_migrate/5e1b1d66757e135433fb3094ef4f21a7.png)
在启动前,我们需要修改下application.properties的配置,找到rocketmq.config.namesrvAddr配置,添加nameServer的ip与端口,这里我们连接的是本地应用,直接填写localhost:9876:
server.port=8180
...
rocketmq.config.namesrvAddr=localhost:9876
...
复制代码
启动,结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/60d50906c0e08b94340c15b8c071c339.png)
访问http://localhost:8180,结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/5211e81c7050d2c887415dac2e7de54a.png)
可以看到broker已经出现在cluster列表中了,这就表明启动成功了。
4. 收发消息测试
rocketMq项目的example模块下有大量的测试示例,我们选择quickstart进行消息收发测试。
4.1 启动Consumer
我们先找到org.apache.rocketmq.example.quickstart.Consumer,增加:
![](https://i-blog.csdnimg.cn/blog_migrate/258692a2225878d0cd8f473500be342f.png)
这个Consumer监听的topic是TopicTest,后面我们就会往这个topic发送消息。另外,需要注意nameServer的配置,我们是在本地启动的nameServer,因此这里配置的是127.0.0.1:9876。
运行main()方法,结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8a0c72bdd3a0c9684fc785d904909666.png)
4.2 启动Producer
我们找到 org.apache.rocketmq.example.quickstart.Producer 类,增加
![](https://i-blog.csdnimg.cn/blog_migrate/bb954ab7b0a2d747e9be2a9f09efb98c.png)
同样地,这里使用的是的nameServer地址是127.0.0.1:9876,topic 是TopicTest,运行,结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/94114f488b833b2a9cb9aa222e13915a.png)
再回过头看看Consumer的控制台:
![](https://i-blog.csdnimg.cn/blog_migrate/bf6152881287a24ef9919f20db332f0a.png)
可以看到,Producer发送消息成功了,Consumer也成功获取到消息了。
4.3 异常分析
如图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/c4e683d27bca254c685d2a56bee99b92.png)
如果出现异常:
org.apache.rocketmq.client.exception.MQClientException:
No route info of this topic: TopicTest
复制代码
复制代码
这表明当前broker中没有TopicTest的topic,这时我们可以手动创建topic,也可以在启动时指定autoCreateTopicEnable=true.
如果是按上面步骤进行的,请确认下org.apache.rocketmq.broker.BrokerStartup是否配置启动参数
-n localhost:9876 autoCreateTopicEnable=true复制代码
配置方式就按3.3节的方式配置就行了。
5. 日志配置
在启动的时候,日志配置文件是将日志打印到${user.name},自己认为不好找日志,就把日志打印到ROCKETMQ_HOME下的logs配置文件中,需要将日志文件中的user.name替换为:ROCKETMQ_HOME,然后重启,就会将日志记录到自定义的logs下:
![](https://i-blog.csdnimg.cn/blog_migrate/0002623743b37a29a1d7a517e96b6f05.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b3b49ac3a6ed19cfc22ceab5f9ce12bd.png)
6. 总结
本文主要介绍了rocketMq的基本架构,通过源码展示了rocketMq的启动方式,最后通过rocketMq项目下example模块中的测试代码展示了消息的收发过程。
总的来说,本文还是在准备源码分析的环境,下篇文章开始,我们就正式开始rocketMq的源码分析了。
作者:hsfxuebao