快速搭建RocketMQ集群

前言:最近在学习了解RocketMQ,为了更好地对照了解,需要安装一套RocketMQ集群,自己实际上手操作一番。首先在google搜索一番,找了一篇教程,看了下,比较详细,参考程度很高。特搬运过来。作为一个小白,开始一步步地实地操作起来,如果有对RocketMQ感兴趣的新手们,也可以跟我一起学习起来。
我想了一个学习方法,叫做启发扩散式学习。在本文最后,列出由本文操作引出的扩散问题,及相关问题的搜索学习解答。

1、搭建机器环境

准备3台虚拟机,用户名和密码都是root,ip地址如下所示

在三台机上修改/etc/hosts,增加以下内容:

192.168.3.8 worker1
192.168.3.9 worker2
192.168.3.10 worker3

2、创建用户

useradd user
passwd user (密码输入123qweasd)

3、系统配置

免密登录

切换user用户,在worker1上生成key,ssh-kengen然后分发给其他机器

ssh-copy-id worker1 
ssh-copy-id worker2
ssh-copy-id worker3


关闭防火墙


systemctl stop firewalld.service
firewall-cmd--state


4、安装java


给user创建/app目录 上传jdk的tar包 修改~/.bash_profile, 配置环境变量。使source生效。

export JAVA_HOME=/app/jdk1.8/



5、安装RocketMQ

上传RocketMQ的tar包,直接解压。然后配置环境变量

export ROCKETMQ_HOME=/app/rocketmq/rocketmq-all-4.7.1-bin-release

RocketMQ在4.5版本之前都不支持master宕机后slave自动切换。在4.5版本后,增加了基于Dleger实现的主从切换。这里用的目前最新的4.7.1版本

6、配置RocketMQ集群

预计搭建2主2从异步刷盘的集群

机器名

nemaeServer节点部署

broker节点部署

worker1

nameserver

worker2

nameserver

broker-a, broker-b-s

worker3

nameserver

broker-b,broker-a-s

修改的配置文件是进入rocketmq的config目录下修改2m-2s-async的配置文件。

2m-2s-async搭建优点

  • 2m-2s-async: 2主2从异步刷盘(吞吐量较大,但是消息可能丢失)
  • 2m-2s-sync:2主2从同步刷盘(吞吐量会下降,但是消息更安全)
  • 2m-noslave:2主无从(单点故障),然后还可以直接配置broker.conf,进行单点环境配置
  • 而dleger就是用来实现主从切换的。集群中的节点会基于Raft协议随机选举出一个leader,其他的就都是follower。通常正式环境都会采用这种方式来搭建集群

1)、配置第一组broker-a

worker2配置borker-a的master节点

先配置2m-2s-async/broker-a.properties

#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=rocketmq-cluster
#broker名字,名字一样的节点就是一组主从节点。
brokerName=broker-a
#brokerid,0就表示是Master,>0的都是表示Slave
brokerId=0
#nameServer地址,分号分割
namesrvAddr=worker1:9876;worker2:9876;worker3:9876
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许Broker自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许Broker自动创建订阅组,建议线下开启,线上关闭autoCreateSubscriptionGroup=true
#Broker对外服务的监听端口
listenPort=10911
#删除文件时间点,默认凌晨4点
deleteWhen=04
#文件保留时间,默认48小时
fileReservedTime=120
#commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30W条,根据业务情况调整mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/app/rocketmq/store
#commitLog存储路径
storePathCommitLog=/app/rocketmq/store/commitlog
#消费队列存储路径存储路径
storePathConsumeQueue=/app/rocketmq/store/consumequeue
#消息索引存储路径
storePathIndex=/app/rocketmq/store/index
#checkpoint文件存储路径
storeCheckpoint=/app/rocketmq/store/checkpoint
#abort文件存储路径
abortFile=/app/rocketmq/store/abort
#限制的消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000
#Broker的角色
#-ASYNC_MASTER异步复制Master
#-SYNC_MASTER同步双写Master
#-SLAVE
brokerRole=ASYNC_MASTER
#刷盘方式
#-ASYNC_FLUSH异步刷盘
#-SYNC_FLUSH同步刷盘
flushDiskType=ASYNC_FLUSH
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128


worker3配置borker-a的salve节点,broker-a-s.properties


只需要修改brokerId和brokerRole

#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=rocketmq-cluster
#broker名字,名字一样的节点就是一组主从节点。
brokerName=broker-a
#brokerid,0就表示是Master,>0的都是表示Slave
brokerId=1
#nameServer地址,分号分割
namesrvAddr=worker1:9876;worker2:9876;worker3:9876
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许Broker自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许Broker自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#Broker对外服务的监听端口
listenPort=11011
#删除文件时间点,默认凌晨4点
deleteWhen=04
#文件保留时间,默认48小时
fileReservedTime=120
#commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30W条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/app/rocketmq/storeSlave
#commitLog存储路径
storePathCommitLog=/app/rocketmq/storeSlave/commitlog
#消费队列存储路径存储路径
storePathConsumeQueue=/app/rocketmq/storeSlave/consumequeue
#消息索引存储路径
storePathIndex=/app/rocketmq/storeSlave/index
#checkpoint文件存储路径
storeCheckpoint=/app/rocketmq/storeSlave/checkpoint
#abort文件存储路径
abortFile=/app/rocketmq/storeSlave/abort
#限制的消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000
#Broker的角色
#-ASYNC_MASTER异步复制Master
#-SYNC_MASTER同步双写Master
#-SLAVE
brokerRole=SLAVE
#刷盘方式
#-ASYNC_FLUSH异步刷盘
#-SYNC_FLUSH同步刷盘
flushDiskType=ASYNC_FLUSH
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128



2)、配置第二组Broker-b

worker3配置borker-b的master节点

需要配置worker3上的config/2m-2s-async/broker-b.properties


#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=rocketmq-cluster
enablePropertyFilter=true
#broker名字,名字一样的节点就是一组主从节点。
brokerName=broker-b
#brokerid,0就表示是Master,>0的都是表示Slave
brokerId=0
#nameServer地址,分号分割
namesrvAddr=worker1:9876;worker2:9876;worker3:9876
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许Broker自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许Broker自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#Broker对外服务的监听端口
listenPort=10911
#删除文件时间点,默认凌晨4点
deleteWhen=04
#文件保留时间,默认48小时
fileReservedTime=120
#commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30W条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/app/rocketmq/store
#commitLog存储路径
storePathCommitLog=/app/rocketmq/store/commitlog
#消费队列存储路径存储路径
storePathConsumeQueue=/app/rocketmq/store/consumequeue
#消息索引存储路径
storePathIndex=/app/rocketmq/store/index
#checkpoint文件存储路径
storeCheckpoint=/app/rocketmq/store/checkpoint
#abort文件存储路径
abortFile=/app/rocketmq/store/abort
#限制的消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000
#Broker的角色
#-ASYNC_MASTER异步复制Master
#-SYNC_MASTER同步双写Master
#-ASYNC_MASTER
brokerRole=ASYNC_MASTER
#刷盘方式
#-ASYNC_FLUSH异步刷盘
#-SYNC_FLUSH同步刷盘
flushDiskType=ASYNC_FLUSH
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128


worker2配置borker-b的salve节点,broker-b-s.properties


修改work2上的conf/2m-2s-async/broker-b-s.properties


#所属集群名字,名字一样的节点就在同一个集群内
brokerClusterName=rocketmq-cluster
#broker名字,名字一样的节点就是一组主从节点。
brokerName=broker-b
#brokerid,0就表示是Master,>0的都是表示Slave
brokerId=1
#nameServer地址,分号分割
namesrvAddr=worker1:9876;worker2:9876;worker3:9876
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许Broker自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许Broker自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#Broker对外服务的监听端口
listenPort=11011
#删除文件时间点,默认凌晨4点
deleteWhen=04
#文件保留时间,默认48小时
fileReservedTime=120
#commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30W条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/app/rocketmq/storeSlave
#commitLog存储路径
storePathCommitLog=/app/rocketmq/storeSlave/commitlog
#消费队列存储路径存储路径
storePathConsumeQueue=/app/rocketmq/storeSlave/consumequeue
#消息索引存储路径
storePathIndex=/app/rocketmq/storeSlave/index
#checkpoint文件存储路径
storeCheckpoint=/app/rocketmq/storeSlave/checkpoint
#abort文件存储路径
abortFile=/app/rocketmq/storeSlave/abort
#限制的消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000
#Broker的角色
#-ASYNC_MASTER异步复制Master
#-SYNC_MASTER同步双写Master
#-SLAVE
brokerRole=SLAVE
#刷盘方式
#-ASYNC_FLUSH异步刷盘
#-SYNC_FLUSH同步刷盘
flushDiskType=ASYNC_FLUSH
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128



3)、其他注意

  • 1、同一机器上两个实例的store目录不能相同,否则会报错Lock failed,MQalready started
  • 2、同一机器上两个实例的listenPort也不能相同。否则会报端口占用的错nameserver不需要进行配置,直接启动就行。这也看出nameserver是无状态的。

7、启动RocketMQ

1)、启动nameServer

  • 修改三个节点上的bin/runserver.sh,调整里面的jvm内存配置。
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m 
-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
  • 三个节点上启动nameServer
nohup bin/mqnamesrv &
  • 使用jps指令可以查看NamesrvStartup进程是否启动成功

2)、启动broker

启动broker是使用的mqbroker指令,只是注意启动broker时需要通过-c指定对应的配置文件。

  • worker2启动broker-a的master节点和broker-b的slave节点
nohup ./mqbroker -c ../conf/2m-2s-async/broker-a.properties &
nohup ./mqbroker -c ../conf/2m-2s-async/broker-b-s.properties &



  • work3启动broker-b的master节点和broker-a的slave节点
nohup ./mqbroker -c ../conf/2m-2s-async/broker-b.properties & 
nohup ./mqbroker -c ../conf/2m-2s-async/broker-a-s.properties &



  • 注意

启动slave时,如果遇到报错Lock failed,MQ already started,那是因为有多个实例共用了同一个storePath造成的,这时就需要调整store的路径。

3)、启动状态检查

  • 使用jps

使用jps查看NameSrvStartup进程和两个BrokerStartup进程

  • 查看nohup.out日志
#查看nameServer日志
tail -500f ~/logs/rocketmqlogs/namesrv.log
#查看broker日志
tail-500f ~/logs/rocketmqlogs/broker.log



4)、命令行快速验证

在RocketMQ的安装包中,提供了一个tools.sh工具可以用来在命令行快速验证RocketMQ服务。我们在worker2上进入RocketMQ的安装目录:

  •  配置一个环境变量NAMESRV_ADDR,指定NameServer地址
export NAMESRV_ADDR='worker1:9876;worker2:9876;worker3:9876'
  • 发送消息:默认会发1000条消息
bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
  • 接收消息
bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer

8、搭建管理控制台

RocketMQ源代码中并没有提供控制台,但是有一个Rocket的社区扩展项目中提供了一个控制台,地址:https://github.com/apache/rocketmq-dashboard

下载下来后,进入其中的rocketmq-dashboard目录,使用maven进行编译

mvn clean package -Dmaven.test.skip=true



编译完成后,获取target下的jar包,就可以直接执行。但是这个时候要注意,在这个项目的application.yml中需要指定nameserver的地址。默认这个属性是空的。那我们可以在jar包的当前目录下增加一个application.yml文件,覆盖jar包中默认的一个属性:

rocketmq:
  config:
    # if this value is empty,use env value rocketmq.config.namesrvAddr  NAMESRV_ADDR | now, default localhost:9876
    # configure multiple namesrv addresses to manage multiple different clusters
    namesrvAddrs:
      - worker1:9876
      - worker2:9876
      - worker3:9876



  • 执行jar
java -jar target/rocketmq-dashboard-1.0.1-SNAPSHOT.jar



启动完成后,可以访问http://192.168.3.10:8080看到管理页

1)注:

搭建管理平台Dashboard的时候碰到两个问题

(1)8080端口被占用了。使用netstat -tunlp |grep 8080  查看是哪个进程占用。但是在user用户,使用这个命令时,只能显示8080端口使用详情,但是不能显示占用进程号与进程名:

$ netstat -tunlp |grep 8080
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp6       0      0 :::8080                   :::*                    LISTEN      -

切换到root用户才能显示出占用的进程。

# netstat -tunlp |grep 8080
tcp6       0      0 :::8080                   :::*                    LISTEN      9115/docker-proxy

(2)Dashboard启动成功打开页面访问,跳出错误信息,broker连接错误:172.17.2.0.  看了下日志,发现从namesrv上获取的集群信息里,broker的地址都不对。想了下,原来启动broker的机子上,都有多个IP。看来是broker启动时自己绑定到了一个外面不对访问的地址上了。网卡搜了下,broker配置文件里可以使用配置项brokerIP1(外部访问)和brokerIP2(SLAVE访问)两个来配置应用启动要绑定的IP。

全文启发式学习注:

    待解决疑问:

1、为什么要创建user用户,是怎么使用上user用户的,都在user用户下执行操作吗。为什么不用root用户?

答:应该是为了RocketMQ的进程和相关文件能够单独管理,防止root用户被滥用。不是太确定还有什么特殊的原因。因为有点困惑,之前部署过k8s,部署k8s的时候,有很大不同,全程都用的root用户。

2、dashboard 覆盖nameserv的配置,是使用application.properties还是使用application.yml文件。为什么放jar包同目录可以覆盖里面的配置,是什么原理,是因为springboot的作用原理么。

答:是springboot的默认配置文件。

3、dledger是一个什么样的存在,需要稍微了解一下。与Raft协议的关系是什么,Raft协议又是什么。

答:dledger是针对RocketMQ实现的一套主备切换,自动选主的方案。基于部分Raft协议。之前还以为dledger是其它早先早就有的一个技术,查过后才知道,这个RocketMQ团队,从RocketMQ才发明出来,刚开始用起来的。

Ratf协议是工程上使用较广泛的一致性,去中心化,高可用的分布式协议。

Ratf是一种共识算法,所谓共识,就是对某一件事达成一致的看法。有专门的博士论文介绍这个算法。所以这个要展开来,应该是一个比较大的主题了。有空再去试试研究一下。