前言:最近在学习了解RocketMQ,为了更好地对照了解,需要安装一套RocketMQ集群,自己实际上手操作一番。首先在google搜索一番,找了一篇教程,看了下,比较详细,参考程度很高。特搬运过来。作为一个小白,开始一步步地实地操作起来,如果有对RocketMQ感兴趣的新手们,也可以跟我一起学习起来。
我想了一个学习方法,叫做启发扩散式学习。在本文最后,列出由本文操作引出的扩散问题,及相关问题的搜索学习解答。
准备3台虚拟机,用户名和密码都是root,ip地址如下所示
在三台机上修改/etc/hosts,增加以下内容:
192.168.3.8 worker1192.168.3.9 worker2192.168.3.10 worker3
2、创建用户
useradd userpasswd user (密码输入123qweasd)
3、系统配置
切换user用户,在worker1上生成key,ssh-kengen然后分发给其他机器
ssh-copy-id worker1ssh-copy-id worker2ssh-copy-id worker3
关闭防火墙
systemctl stop firewalld.servicefirewall-cmd--state
4、安装java
给user创建/app目录 上传jdk的tar包 修改~/.bash_profile, 配置环境变量。使source生效。
export JAVA_HOME=/app/jdk1.8/
上传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版本
| 机器名 | 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: 2主2从异步刷盘(吞吐量较大,但是消息可能丢失)
2m-2s-sync:2主2从同步刷盘(吞吐量会下降,但是消息更安全)
2m-noslave:2主无从(单点故障),然后还可以直接配置broker.conf,进行单点环境配置
而dleger就是用来实现主从切换的。集群中的节点会基于Raft协议随机选举出一个leader,其他的就都是follower。通常正式环境都会采用这种方式来搭建集群
worker2配置borker-a的master节点
先配置2m-2s-async/broker-a.properties
#所属集群名字,名字一样的节点就在同一个集群内brokerClusterName=rocketmq-cluster#broker名字,名字一样的节点就是一组主从节点。brokerName=broker-a#brokerid,0就表示是Master,>0的都是表示SlavebrokerId=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每个文件的大小默认1GmapedFileSizeCommitLog=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#-SLAVEbrokerRole=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的都是表示SlavebrokerId=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每个文件的大小默认1GmapedFileSizeCommitLog=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#-SLAVEbrokerRole=SLAVE#刷盘方式#-ASYNC_FLUSH异步刷盘#-SYNC_FLUSH同步刷盘flushDiskType=ASYNC_FLUSH#checkTransactionMessageEnable=false#发消息线程池数量#sendMessageThreadPoolNums=128#拉消息线程池数量#pullMessageThreadPoolNums=128
worker3配置borker-b的master节点
需要配置worker3上的config/2m-2s-async/broker-b.properties
#所属集群名字,名字一样的节点就在同一个集群内brokerClusterName=rocketmq-clusterenablePropertyFilter=true#broker名字,名字一样的节点就是一组主从节点。brokerName=broker-b#brokerid,0就表示是Master,>0的都是表示SlavebrokerId=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每个文件的大小默认1GmapedFileSizeCommitLog=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_MASTERbrokerRole=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的都是表示SlavebrokerId=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每个文件的大小默认1GmapedFileSizeCommitLog=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#-SLAVEbrokerRole=SLAVE#刷盘方式#-ASYNC_FLUSH异步刷盘#-SYNC_FLUSH同步刷盘flushDiskType=ASYNC_FLUSH#checkTransactionMessageEnable=false#发消息线程池数量#sendMessageThreadPoolNums=128#拉消息线程池数量#pullMessageThreadPoolNums=128
1、同一机器上两个实例的store目录不能相同,否则会报错Lock failed,MQalready started
2、同一机器上两个实例的listenPort也不能相同。否则会报端口占用的错nameserver不需要进行配置,直接启动就行。这也看出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进程是否启动成功
启动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的路径。
使用jps
使用jps查看NameSrvStartup进程和两个BrokerStartup进程
查看nohup.out日志
#查看nameServer日志tail -500f ~/logs/rocketmqlogs/namesrv.log#查看broker日志tail-500f ~/logs/rocketmqlogs/broker.log
在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
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 clustersnamesrvAddrs:- 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 infowill not be shown, you would have to be root to see it all.)tcp6 0 0 :::8080 :::* LISTEN -
切换到root用户才能显示出占用的进程。
# netstat -tunlp |grep 8080tcp6 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是一种共识算法,所谓共识,就是对某一件事达成一致的看法。有专门的博士论文介绍这个算法。所以这个要展开来,应该是一个比较大的主题了。有空再去试试研究一下。
本文大部分内容引用自https://juejin.cn/post/7046583211027071013
在这个基础上做了些注解与补充修整。