【RocketMq源码篇-02】rocketmq集群搭建详细过程(docker版-2主2从)

202 阅读12分钟

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

1763908908223.png 在这里选择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的配置

NamebrokerIdportbrokerRole
brokerA-masterBrokerA010911ASYNC_MASTER
brokerA-slaveBrokerA110911SLAVE
brokerB-masterBrokerB010911ASYNC_MASTER
brokerB-slaveBrokerB110911SLAVE
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

最后的文件配置分布如下

1763211591021.png

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

1763310608608.png

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

1763233223586.png

2.2.2,端口映射

端口映射关系如下

  • 10909端口是回查端口,比如正常rpc的远程调用、通信,如果没有这个端口,那么事务消息几乎无法正常使用。比如Producer发送半消息,Broker接收到消息之后,需要等待Producer执行本地事务,若事务不明确,那么就需要会查事务状态,Broker会主动回调Producer监听器方法,这个回调就是走的10909端口
  • 10911端口是主通信端口,是最核心的端口,必须对外暴露,不然集群不可用。主要业务有:发送消息、拉取消息、心跳、更新消费进度、获取topic路由、消费者负载均衡等
回传端口通信端口
brokerA-master10909:1090910911:10911
brokerA-slave20909:2090920911:20911
brokerB-master11909:1190911911:11911
brokerB-slave21909:2190921911: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

随后就会看到下面拉取镜像和镜像启动的画面。第一次启动可能会比较慢,因为要下载好几个镜像文件。在下载完成之后会自动的启动所有容器

1763275939809.png

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

1763278192150.png

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

docker ps

1763308785121.png 启动信息如下

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,意味着主程序就是启动失败

1763283521917.png

首先给这个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

1763384369083.png

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

1763386123391.png

最后查看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

此时消息发送成功,发送日志如下

1763386614807.png

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

1763387517174.png

此时消费者也能测试测试成功!

4,总结

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

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