RocketMq源码核心篇整体栏目
| 内容 | 链接地址 |
|---|---|
| 【一】环境搭建、基本使用、可视化界面 | https://zhenghuisheng.blog.csdn.net/article/details/147481401 |
| 【二】rocketmq集群搭建(docker版-2主2从) | https://zhenghuisheng.blog.csdn.net/article/details/154921615 |
rocketmq集群搭建
- 一,rocketmq集群搭建(docker版)
-
- 1,虚拟机和centos搭建
- 2,docker搭建集群
- 3,集群验证
-
- [3.1, NameServer 启动情况](#3.1, NameServer 启动情况)
- [3.2, 路由信息同步情况](#3.2, 路由信息同步情况)
- 3.3,producer发送消息
- 3.4,主从复制测试
- 3.5,consumer消费消息
- 4,总结
一,rocketmq集群搭建(docker版)
前面文章将讲解了rocketmq的单机搭建和基本使用,在实际公司或者大厂中,为了保证高性能和高可用,都会搭建多台机器来实现。比如说集群搭建 来保证高可用,即使是有一台机器坏了,也能通过另外的机器来保证流程的高可用;然后通过主从复制,读写分离的方式实现高性能,比如主库用来读,从库用来写的方式实现高性能。
本篇章主要就是通过docker来搭建一个两主两从的集群,由于每一个broker是无状态的,就是不会像zookeeper或者redis集群那样,需要维护心跳和投票等机制来进行选举,因此在搭建集群的时候,就不需要考虑奇数,比如搭建一个redis的cluster集群,那么就要设置3个或者5个服务。
因此结合高可用和高性能,以及rocketmq无状态的机制,接下来就搭建一个2主2从的Rocketmq集群,由于本人只有一台虚拟机,所以在一台机器上模拟4个broker

在这里选择4.9.4的版本来研究整个rocketmq源码,和我前面的版本保持一致
1,虚拟机和centos搭建
1.1,虚拟机安装和激活
vmware虚拟机用的版本是17,可以直接去官网下载:https://support.broadcom.com/group/ecx/productdownloads?subfamily=VMware Workstation Pro
1.2,ubuntu镜像
ios我这边选择是ubuntu的镜像,大家也可以选择centos的镜像,但是在安装东西这块Ubuntu会比centos爽很多,稍微大点的企业的运维用ubuntu系统比较多,而且ubuntu开源,社区比较活跃,官方文档也比较齐全,因此选择ubuntu。其官网下载地址如下:https://ubuntu.com/download/server ,本人是选择是这个版本,维护时间比较长,并且开源免费,打开网页直接下载即可
2,docker搭建集群
接下来通过docker来搭建整个集群,docker的安装可以直接参考官网,也可以直接看本人前面的文章。
因为需要docker和compose的结合使用,因此需要查看一下compose的版本,有版本输出就行
java
docker compose version
2.1,Broker配置文件编辑
首先先建一个配置文件夹,我这边建 /usr/local/env/rocketmq/cluster 文件夹,并在该文件夹下面新建conf、logs、store文件夹
java
mkdir -p /usr/local/env/rocketmq/cluster
mkdir -p /usr/local/env/rocketmq/cluster/{conf,logs,store}
然后给这些文件夹权限
java
sudo chown -R $USER:$USER /usr/local/env/rocketmq/cluster
随后在这个conf文件夹下,新建以下四个文件:brokerA-master.conf、brokerB-master.conf、brokerA-slave.conf、brokerB-slave.conf,分别代表这4个broker的配置
| Name | brokerId | port | brokerRole | |
|---|---|---|---|---|
| brokerA-master | BrokerA | 0 | 10911 | ASYNC_MASTER |
| brokerA-slave | BrokerA | 1 | 10911 | SLAVE |
| brokerB-master | BrokerB | 0 | 10911 | ASYNC_MASTER |
| brokerB-slave | BrokerB | 1 | 10911 | SLAVE |
2.1.1,brokerA-master.conf
BrokerA-Master的配置文件如下,brokerName的名称设置为BrokerA,端口设置为10911,开启异步刷盘,brokerRole角色设置为 ASYNC_MASTER,brokerId=0
java
brokerClusterName=DefaultCluster
brokerName=BrokerA
brokerId=0
listenPort=10911
namesrvAddr=namesrv:9876
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
storePathConsumerQueue=/home/rocketmq/store/consumequeue
storePathIndex=/home/rocketmq/store/index
autoCreateTopicEnable=true
flushDiskType=ASYNC_FLUSH
brokerRole=ASYNC_MASTER
2.1.2,brokerA-slave.conf
BrokerA-Slave的配置文件如下,brokerName的名称设置为BrokerA,端口设置为10911,异步刷盘,brokerRole角色设置为Slave,brokerId = 1
java
brokerClusterName=DefaultCluster
brokerName=BrokerA
brokerId=1
listenPort=10911
namesrvAddr=namesrv:9876
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
storePathConsumerQueue=/home/rocketmq/store/consumequeue
storePathIndex=/home/rocketmq/store/index
autoCreateTopicEnable=true
flushDiskType=ASYNC_FLUSH
brokerRole=SLAVE
2.1.3,brokerB-master.conf
BrokerB-Master的配置文件如下,brokerName的名称设置为BrokerB,端口设置为10911,异步刷盘,brokerRole角色设置为ASYNC_MASTER,brokerId = 0
java
brokerClusterName=DefaultCluster
brokerName=BrokerB
brokerId=0
listenPort=10911
namesrvAddr=namesrv:9876
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
storePathConsumerQueue=/home/rocketmq/store/consumequeue
storePathIndex=/home/rocketmq/store/index
autoCreateTopicEnable=true
flushDiskType=ASYNC_FLUSH
brokerRole=ASYNC_MASTER
2.1.4,brokerB-slave.conf
BrokerB-Slave的配置文件如下,brokerName的名称设置为BrokerB,端口设置为10911,异步刷盘,brokerRole角色设置为Slave,brokerId = 1
java
brokerClusterName=DefaultCluster
brokerName=BrokerB
brokerId=1
listenPort=10911
namesrvAddr=namesrv:9876
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
storePathConsumerQueue=/home/rocketmq/store/consumequeue
storePathIndex=/home/rocketmq/store/index
autoCreateTopicEnable=true
flushDiskType=ASYNC_FLUSH
brokerRole=SLAVE
最后的文件配置分布如下

2.2,Compose配置
2.2.1,配置详情
在 cluster文件夹下,新建一个docker-compose.yml文件,文件内容如下:
-
镜像统一版本用 apache/rocketmq:4.9.4
-
首先需要一个naveserver的注册中心,这里注册一个rmq-namesrv 容器,类似于zookeeper的注册中心,注册broker和topic等的信息,官方默认的端口号是 9876 ,堆内存的初始大小和最大大小都设置成256m,即
-Xms256m -Xmx256m -
brokerA-master分支的映射端口为
10909和10911,broker需要两个端口,他对外提供两个不同目的的服务,初始堆内存和最大堆内存都设置为1g,即-Xms1g -Xmx1g,挂载的配置文件为 brokerA-master.conf -
brokerA-slave容器的映射端口为
20909和20911,作用和上面的一样,都是映射到容器的10909端口和10911端口。最大堆内存和起始堆内存分别为-Xms512m -Xmx512m,挂载的配置文件为 brokerA-slave.conf -
brokerB-master容器的映射端口为
11909和11911。最大堆内存和起始堆内存分别为-Xms1g -Xmx1g,挂载的配置文件为 brokerB-master.conf -
brokerB-slave容器的映射端口为
21909和21911。最大堆内存和起始堆内存分别为-Xms512m -Xmx512m,挂载的配置文件为 brokerB-slave.conf -
最后网络设置为bridge桥接模式
yml
version: '3.8'
services:
namesrv:
image: apache/rocketmq:4.9.4
container_name: rmq-namesrv
command: sh -c "export JAVA_OPT_EXT='-server -Xms512m -Xmx512m -Xmn256m' && cd /home/rocketmq/rocketmq-4.9.4/bin && ./mqnamesrv"
ports:
- "9876:9876"
volumes:
- /usr/local/env/rocketmq/cluster/logs/namesrv:/home/rocketmq/logs
- /usr/local/env/rocketmq/cluster/store/namesrv:/home/rocketmq/store
networks:
- rmq
brokerA-master:
image: apache/rocketmq:4.9.4
container_name: rmq-brokerA-master
command: >
sh -c "
export JAVA_OPT_EXT='-server -Xms1g -Xmx1g -Xmn256m' &&
cd /home/rocketmq/rocketmq-4.9.4/bin &&
./mqbroker -c /home/rocketmq/broker.conf
"
depends_on:
- namesrv
environment:
- NAMESRV_ADDR=namesrv:9876
ports:
- "10911:10911"
- "10909:10909"
volumes:
- /usr/local/env/rocketmq/cluster/conf/brokerA-master.conf:/home/rocketmq/broker.conf
- /usr/local/env/rocketmq/cluster/logs/brokerA-master:/home/rocketmq/logs
- /usr/local/env/rocketmq/cluster/store/brokerA-master:/home/rocketmq/store
networks:
- rmq
brokerA-slave:
image: apache/rocketmq:4.9.4
container_name: rmq-brokerA-slave
command: >
sh -c "
export JAVA_OPT_EXT='-server -Xms512m -Xmx512m -Xmn256m' &&
cd /home/rocketmq/rocketmq-4.9.4/bin &&
./mqbroker -c /home/rocketmq/broker.conf
"
depends_on:
- brokerA-master
environment:
- NAMESRV_ADDR=namesrv:9876
ports:
- "20911:10911"
- "20909:10909"
volumes:
- /usr/local/env/rocketmq/cluster/conf/brokerA-slave.conf:/home/rocketmq/broker.conf
- /usr/local/env/rocketmq/cluster/logs/brokerA-slave:/home/rocketmq/logs
- /usr/local/env/rocketmq/cluster/store/brokerA-slave:/home/rocketmq/store
networks:
- rmq
brokerB-master:
image: apache/rocketmq:4.9.4
container_name: rmq-brokerB-master
command: >
sh -c "
export JAVA_OPT_EXT='-server -Xms1g -Xmx1g -Xmn256m' &&
cd /home/rocketmq/rocketmq-4.9.4/bin &&
./mqbroker -c /home/rocketmq/broker.conf
"
depends_on:
- namesrv
environment:
- NAMESRV_ADDR=namesrv:9876
ports:
- "11911:10911"
- "11909:10909"
volumes:
- /usr/local/env/rocketmq/cluster/conf/brokerB-master.conf:/home/rocketmq/broker.conf
- /usr/local/env/rocketmq/cluster/logs/brokerB-master:/home/rocketmq/logs
- /usr/local/env/rocketmq/cluster/store/brokerB-master:/home/rocketmq/store
networks:
- rmq
brokerB-slave:
image: apache/rocketmq:4.9.4
container_name: rmq-brokerB-slave
command: >
sh -c "
export JAVA_OPT_EXT='-server -Xms512m -Xmx512m -Xmn256m' &&
cd /home/rocketmq/rocketmq-4.9.4/bin &&
./mqbroker -c /home/rocketmq/broker.conf
"
depends_on:
- brokerB-master
environment:
- NAMESRV_ADDR=namesrv:9876
ports:
- "21911:10911"
- "21909:10909"
volumes:
- /usr/local/env/rocketmq/cluster/conf/brokerB-slave.conf:/home/rocketmq/broker.conf
- /usr/local/env/rocketmq/cluster/logs/brokerB-slave:/home/rocketmq/logs
- /usr/local/env/rocketmq/cluster/store/brokerB-slave:/home/rocketmq/store
networks:
- rmq
networks:
rmq:
driver: bridge
不同的版本可能 挂在的位置不一样,需要进去容器内部找到conf配置文件的路径,如4.9.4版本中,那么其挂载位置在 /home/rocketmq/broker.conf 目录下,其他的logs和store都在这个 /home/rocketmq 文件下
保存后在外面cat看看保存成功了没有,成功就会将刚刚配置的yml文件显示
java
cat docker-compose.yml

文件结构的的整体目录如下,像logs和store下面的文件夹不存在的话 也可以递归的创建一下

2.2.2,端口映射
端口映射关系如下
- 10909端口是回查端口,比如正常rpc的远程调用、通信,如果没有这个端口,那么事务消息几乎无法正常使用。比如Producer发送半消息,Broker接收到消息之后,需要等待Producer执行本地事务,若事务不明确,那么就需要会查事务状态,Broker会主动回调Producer监听器方法,这个回调就是走的10909端口
- 10911端口是主通信端口,是最核心的端口,必须对外暴露,不然集群不可用。主要业务有:发送消息、拉取消息、心跳、更新消费进度、获取topic路由、消费者负载均衡等
| 回传端口 | 通信端口 | |
|---|---|---|
| brokerA-master | 10909:10909 | 10911:10911 |
| brokerA-slave | 20909:10909 | 20911:10911 |
| brokerB-master | 11909:10909 | 11911:10911 |
| brokerB-slave | 21909:10909 | 21911:10911 |
rocketMQ的broker在容器内部只能使用固定端口10911/10909,因为它们在broker源码中写死,不支持自定义。因此我们只能在外部映射不同端口
2.3,集群启动
2.3.1,命令启动
上面已经完整的将rocketmq配置文件给配置好,接下来主要是是集群的启动,首先切换到cluster目录下
java
cd /usr/local/env/rocketmq/cluster
随后执行启动命令,sudo看情况要不要,没有权限的话可以加一下
java
sudo docker compose up -d
随后就会看到下面拉取镜像和镜像启动的画面。第一次启动可能会比较慢,因为要下载好几个镜像文件。在下载完成之后会自动的启动所有容器

随后出现以下标志,就意味着整个rocketMq集群安装和启动成功

最后查看容器状态,可以发现全部成功 ,那么到此为止,rocketmq集群搭建成功
java
docker ps

启动信息如下,此时4个broker加一个nameserve全部创建和启动成功
java
zhenghuisheng@zhenghuisheng-server:/usr/local/env/rocketmq/cluster/conf$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55969ea2e9ee apache/rocketmq:4.9.4 "sh -c ' export JAVA..." 7 seconds ago Up 6 seconds 9876/tcp, 10912/tcp, 0.0.0.0:20909->10909/tcp, [::]:20909->10909/tcp, 0.0.0.0:20911->10911/tcp, [::]:20911->10911/tcp rmq-brokerA-slave
53d9375ba218 apache/rocketmq:4.9.4 "sh -c ' export JAVA..." 7 seconds ago Up 6 seconds 9876/tcp, 10912/tcp, 0.0.0.0:21909->10909/tcp, [::]:21909->10909/tcp, 0.0.0.0:21911->10911/tcp, [::]:21911->10911/tcp rmq-brokerB-slave
c9a32ab5b293 apache/rocketmq:4.9.4 "sh -c ' export JAVA..." 7 seconds ago Up 6 seconds 0.0.0.0:10909->10909/tcp, [::]:10909->10909/tcp, 9876/tcp, 10912/tcp, 0.0.0.0:10911->10911/tcp, [::]:10911->10911/tcp rmq-brokerA-master
276926d840a5 apache/rocketmq:4.9.4 "sh -c ' export JAVA..." 7 seconds ago Up 6 seconds 9876/tcp, 10912/tcp, 0.0.0.0:11909->10909/tcp, [::]:11909->10909/tcp, 0.0.0.0:11911->10911/tcp, [::]:11911->10911/tcp rmq-brokerB-master
c69ea0e275fd apache/rocketmq:4.9.4 "sh -c ' export JAVA..." 7 seconds ago Up 7 seconds 10909/tcp, 0.0.0.0:9876->9876/tcp, [::]:9876->9876/tcp, 10911-10912/tcp rmq-namesrv
2.4,报错排查
2.4.1,docker下载慢
如果下载的很慢,可以查看以下docker的镜像加速器,编辑下面这个json文件,也可以直接vim
java
sudo nano /etc/docker/daemon.json
然后填入下面的镜像源
json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://mirror.ccs.tencentyun.com",
"https://registry.docker-cn.com",
"https://hub-mirror.c.163.com"
]
}
随后加载配置,随后重启
java
sudo systemctl daemon-reload
sudo systemctl restart docker
最后执行命令,看控制台有没有打印出这些配置信息
java
docker info | grep -i mirror
如果集群拉取的慢,那么先可以手动的单独拉取一个镜像,单独一个可能会快些,然后再将这个镜像删除,再次执行compose启动就能快速拉取整个集群的镜像
java
sudo docker pull rocketmqinc/rocketmq:4.9.4
sudo docker rmi asdbaojdcs
sudo docker compose up -d
2.4.2,端口打开
我这里用的是虚拟机,如果有用到阿里云或者腾讯云等的服务器,那么需要看看端口和防火墙是否打开,按理来说是需要手动的打开用到的五个端口的,分别是 9876、10909、10911、21909、21911
2.4.3,启动失败
如果容器已经创建好了,那么就通过docker ps命令获取所有正在启动的容器,然后没有显示,那么就意味着启动失败,那么就可以通过docker ps -a 看启动过哪些日志
java
docker ps -a
执行完这个命令之后,可以通过下图得知在启动的时候报错了253,意味着主程序就是启动失败

首先给这个conf文件给一定的权限
java
chmod 644 /usr/local/env/rocketmq/cluster/conf/*.conf
检查conf文件中的key/value之间有没有空格,需要把这些空格去掉,value尾部空格也要去掉
java
brokerClusterName=DefaultCluster
检查conf文件中是否存在中文注释,如果存在的话,那么就要把中文注释给删掉。
检查conf文件中的是否不存在换行,查看是否存在 $ 换行符,不存在需要手动调整以下换行
java
cat -A brokerA-master.conf
随后执行以下命令,删除旧容器
java
sudo docker compose down
sudo docker container prune -f
最后执行启动命令,重新加载镜像
java
sudo docker compose up -d
最后,如果linux不好的编写配置,可以现在windows上面先将文件写好,再上传到linux上面
3,集群验证
3.1, NameServer 启动情况
上面已经知道了整个集群已经创建和启动成功,接下来就需要测试里面的功能,首先进入到namesrv容器内部
java
sudo docker exec -it rmq-namesrv bash
随后切换到bin目录下面
java
cd /home/rocketmq/rocketmq-4.9.4/bin
然后直接查看集群
java
./mqadmin clusterList -n localhost:9876
可以看到以下内容
java
#Cluster Name #Broker Name #BID #Addr #Version #InTPS(LOAD) #OutTPS(LOAD) #PCWait(ms) #Hour #SPACE
DefaultCluster BrokerA 0 172.18.0.4:10911 V4_9_4 0.00(0,0ms) 0.00(0,0ms) 0 489828.91 -1.0000
DefaultCluster BrokerA 1 172.18.0.6:10911 V4_9_4 0.00(0,0ms) 0.00(0,0ms) 0 489828.91 0.4800
DefaultCluster BrokerB 0 172.18.0.3:10911 V4_9_4 0.00(0,0ms) 0.00(0,0ms) 0 489828.91 0.4800
DefaultCluster BrokerB 1 172.18.0.5:10911 V4_9_4 0.00(0,0ms) 0.00(0,0ms) 0 489828.91 0.4800

3.2, 路由信息同步情况
主要是看路由信息能不能注册到nameserver中,比如创建一个test的topic
java
./mqadmin updateTopic -n localhost:9876 -t testTopic -c DefaultCluster
执行完命令的结果如下,说明此时路由创建成功
java
create topic to 172.18.0.3:10911 success.
create topic to 172.18.0.4:10911 success.
TopicConfig [topicName=testTopic, readQueueNums=8, writeQueueNums=8, perm=RW-, topicFilterType=SINGLE_TAG, topi...
随后再次执行查看topic的命令
java
./mqadmin topicRoute -n localhost:9876 -t testTopic

最后查看topic列表,可以发现刚刚新建的testtopic就在里面
java
./mqadmin topicList -n localhost:9876
3.3,producer发送消息
接下来测试生产者发送消息,首先进入brokerA-master容器
java
sudo docker exec -it rmq-brokerA-master bash
再次切换到bin目录下
java
cd /home/rocketmq/rocketmq-4.9.4/bin
发送10条消息
java
sh tools.sh org.apache.rocketmq.example.quickstart.Producer
此时消息发送成功,发送日志如下

3.4,主从复制测试
依旧是在这个brokerA-master的容器中,切换到未消费的commitlog目录下
java
cd /home/rocketmq/store/commitlog
brokerA-master的commitlog的便宜量为 1073741824
java
[rocketmq@c9a32ab5b293 commitlog ]$ ls
00000000000000000000 00000000001073741824
再次切换到brokerA-slave的容器中,也是切换到commitlog目录下
java
cd /home/rocketmq/store/commitlog
brokerA-slave的commitlog的便宜量为 0000000
java
[rocketmq@55969ea2e9ee commitlog]$ ls
00000000000000000000
3.5,consumer消费消息
再次进入rmq-brokerA-master这个容器中
java
sudo docker exec -it rmq-brokerA-master bash
切换到这个bin目录下
java
cd /home/rocketmq/rocketmq-4.9.4/bin
随后执行消费的命令
java
sh tools.sh org.apache.rocketmq.example.quickstart.Consumer

此时消费者也能测试测试成功!
4,总结
到此为止,rocketmq集群搭建成功,可以看到我的12核32g的配置使用情况如下,此时内存也占了40%左右,就是将近5g

最后提一下,rocketmq官网4.x版本最新是更新到了4.9.7,但是官网并没有4.9.7的镜像源,本人在此也踩了很多坑,最终还是保持和前面一致的版本,推荐使用了这个4.9.4版本,按照我的配置,以及踩过的坑,就能完整的将整套rocketmq的集群搭建起来