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

RocketMq源码核心篇整体栏目


内容 链接地址
【一】环境搭建、基本使用、可视化界面 https://zhenghuisheng.blog.csdn.net/article/details/147481401
【二】rocketmq集群搭建(docker版-2主2从) https://zhenghuisheng.blog.csdn.net/article/details/154921615

rocketmq集群搭建

一,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的集群搭建起来

相关推荐
qq_2153978973 小时前
docker 管理工具 Portainer安装
运维·服务器·docker
凤凰战士芭比Q3 小时前
Docker安装与常用命令
linux·运维·docker·容器
小坏讲微服务5 小时前
Docker-compose搭建Docker Hub镜像仓库整合SpringBootCloud
运维·分布式·spring cloud·docker·云原生·容器·eureka
AI大模型学徒5 小时前
Docker(五)_数据根目录空间不足的原因与解决方法
运维·docker·容器
惊涛说IT5 小时前
Dockerfile入门案例
docker
无心水7 小时前
【分布式利器:RocketMQ】RocketMQ基本原理详解:架构、流程与核心特性(附实战场景)
中间件·架构·rocketmq·topic·rocketmq基本原理·电商金融mq·nameserver
观望过往7 小时前
Docker Compose CI/CD 集成完全指南:自动化构建、测试与部署
ci/cd·docker·自动化
tianyuanwo11 小时前
Docker Content Trust详解:保障容器镜像安全的信任机制
安全·docker·容器·dct
悟空码字11 小时前
Docker + Spring Boot:天生一对的完美部署
java·后端·docker