RocketMq源码核心篇整体栏目
| 内容 | 链接地址 |
|---|---|
| 【一】环境搭建、基本使用、可视化界面 | zhenghuisheng.blog.csdn.net/article/det… |
| 【二】rocketmq集群搭建(docker版-2主2从) | juejin.cn/editor/draf… |
一,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,可以直接去官网下载:[官网下载地址](support.broadcom.com/group/ecx/p… Workstation Pro)
官网下载不了的话,也可以直接使用本人版本,其链接如下 vmware17 ,提取码: mptm ,如果使用不了,可以在最底下的名片加本人微信私要即可
vmware许可证如下,参考原文链接:vmware许可证 ,需要根据版本一个个去试,本人目前使用的这个 JU090-6039P-08409-8J0QH-2YR7F 是有效的
17:
14A4RR-813DK-M81A9-4U35H-06KND
JU090-6039P-08409-8J0QH-2YR7F
16:
ZF3R0-FHED2-M80TY-8QYGC-NPKYF
FNEW8-ZY7TY-Y1Z7W-QZQCR-NZZ5V
XJKN8-KM9KX-H1Y91-FQPVX-QFXUZ
15:FC7D0-D1YDL-M8DXZ-CYPZE-P2AY6
12:ZC3TK-63GE6-481JY-WWW5T-Z7ATA
10:1Z0G9-67285-FZG78-ZL3Q2-234JG
1.2,ubuntu镜像
ios我这边选择是ubuntu的镜像,大家也可以选择centos的镜像,但是在安装东西这块Ubuntu会比centos爽很多,稍微大点的企业的运维用ubuntu系统比较多,而且ubuntu开源,社区比较活跃,官方文档也比较齐全,因此选择ubuntu。
其官网下载地址如下:ubuntu.com/download/se… ,本人是选择是这个版本,维护时间比较长,并且开源免费,打开网页直接下载即可
如果下面的网页打不开或者实在不想等,那么本人帮各位下载好了,直接从我的网盘里面获取即可,其链接如下:ubuntu镜像
2,docker搭建集群
接下来通过docker来搭建整个集群,docker的安装可以直接参考官网,也可以直接看本人前面的文章。
因为需要docker和compose的结合使用,因此需要查看一下compose的版本,有版本输出就行
docker compose version
2.1,Broker配置文件编辑
首先先建一个配置文件夹,我这边建 /usr/local/env/rocketmq/cluster 文件夹,并在该文件夹下面新建conf、logs、store文件夹
mkdir -p /usr/local/env/rocketmq/cluster
mkdir -p /usr/local/env/rocketmq/cluster/{conf,logs,store}
然后给这些文件夹权限
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
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
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
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
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桥接模式
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:20911"
- "20909:20909"
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:11911"
- "11909:11909"
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:21911"
- "21909:21909"
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
保存后在外面cat看看保存成功了没有,成功就会将刚刚配置的yml文件显示
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:20909 | 20911:20911 |
| brokerB-master | 11909:11909 | 11911:11911 |
| brokerB-slave | 21909:21909 | 21911:21911 |
rocketMQ的broker在容器内部只能使用固定端口10911/10909,因为它们在broker源码中写死,不支持自定义。因此我们只能在外部映射不同端口
2.3,集群启动
2.3.1,命令启动
上面已经完整的将rocketmq配置文件给配置好,接下来主要是是集群的启动,首先切换到cluster目录下
cd /usr/local/env/rocketmq/cluster
随后执行启动命令,sudo看情况要不要,没有权限的话可以加一下
sudo docker compose up -d
随后就会看到下面拉取镜像和镜像启动的画面。第一次启动可能会比较慢,因为要下载好几个镜像文件。在下载完成之后会自动的启动所有容器
随后出现以下标志,就意味着整个rocketMq集群安装和启动成功
最后查看容器状态,可以发现全部成功 ,那么到此为止,rocketmq集群搭建成功
docker ps
启动信息如下
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
sudo nano /etc/docker/daemon.json
然后填入下面的镜像源
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://mirror.ccs.tencentyun.com",
"https://registry.docker-cn.com",
"https://hub-mirror.c.163.com"
]
}
随后加载配置,随后重启
sudo systemctl daemon-reload
sudo systemctl restart docker
最后执行命令,看控制台有没有打印出这些配置信息
docker info | grep -i mirror
如果集群拉取的慢,那么先可以手动的单独拉取一个
sudo docker pull rocketmqinc/rocketmq:4.9.4
2.4.2,启动失败
如果容器已经创建好了,那么就通过docker ps命令获取所有正在启动的容器,然后没有显示,那么就意味着启动失败,那么就可以通过docker ps -a 看启动过哪些日志
docker ps -a
执行完这个命令之后,可以通过下图得知在启动的时候报错了253,意味着主程序就是启动失败
首先给这个conf文件给一定的权限
chmod 644 /usr/local/env/rocketmq/cluster/conf/*.conf
检查conf文件中的key/value之间有没有空格,需要把这些空格去掉,value尾部空格也要去掉
brokerClusterName=DefaultCluster
检查conf文件中是否存在中文注释,如果存在的话,那么就要把中文注释给删掉。
检查conf文件中的是否不存在换行,查看是否存在 $ 换行符,不存在需要手动调整以下换行
cat -A brokerA-master.conf
随后执行以下命令,删除旧容器
sudo docker compose down
sudo docker container prune -f
最后执行启动命令,重新加载镜像
sudo docker compose up -d
最后,如果linux不好的编写配置,可以现在windows上面先将文件写好,再上传到linux上面
3,集群验证
3.1, NameServer 启动情况
上面已经知道了整个集群已经创建和启动成功,接下来就需要测试里面的功能,首先进入到namesrv容器内部
sudo docker exec -it rmq-namesrv bash
随后切换到bin目录下面
cd /home/rocketmq/rocketmq-4.9.4/bin
然后直接查看集群
./mqadmin clusterList -n localhost:9876
可以看到以下内容
#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
./mqadmin updateTopic -n localhost:9876 -t testTopic -c DefaultCluster
执行完命令的结果如下,说明此时路由创建成功
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的命令
./mqadmin topicRoute -n localhost:9876 -t testTopic
最后查看topic列表,可以发现刚刚新建的testtopic就在里面
./mqadmin topicList -n localhost:9876
3.3,producer发送消息
接下来测试生产者发送消息,首先进入brokerA-master容器
sudo docker exec -it rmq-brokerA-master bash
再次切换到bin目录下
cd /home/rocketmq/rocketmq-4.9.4/bin
发送10条消息
sh tools.sh org.apache.rocketmq.example.quickstart.Producer
此时消息发送成功,发送日志如下
3.4,主从复制测试
依旧是在这个brokerA-master的容器中,切换到未消费的commitlog目录下
cd /home/rocketmq/store/commitlog
brokerA-master的commitlog的便宜量为 1073741824
[rocketmq@c9a32ab5b293 commitlog ]$ ls
00000000000000000000 00000000001073741824
再次切换到brokerA-slave的容器中,也是切换到commitlog目录下
cd /home/rocketmq/store/commitlog
brokerA-slave的commitlog的便宜量为 0000000
[rocketmq@55969ea2e9ee commitlog]$ ls
00000000000000000000
3.5,consumer消费消息
再次进入rmq-brokerA-master这个容器中
sudo docker exec -it rmq-brokerA-master bash
切换到这个bin目录下
cd /home/rocketmq/rocketmq-4.9.4/bin
随后执行消费的命令
sh tools.sh org.apache.rocketmq.example.quickstart.Consumer
此时消费者也能测试测试成功!
4,总结
到此为止,rocketmq集群搭建成功,可以看到我的12核32g的配置使用情况如下,此时内存也占了40%左右,就是将近5g
最后提一下,rocketmq官网最新是更新到了4.9.7,但是官网并没有4.9.7的镜像源,本人在此也踩了很多坑,最终还是保持和前面一致的版本,推荐使用了这个4.9.4版本,按照我的配置,以及踩过的坑,就能完整的将整套rocketmq的集群搭建起来