RocketMQ学习-RocketMQ实战(二)搭建管理控

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

搭建管理控制台

上篇搭建了RocketMQ主从模式的集群,但是没有解决单点故障问题,master挂掉,服务就不可用了。所以本章将介绍一下使用Dleger搭建一个高可用的集群。

首先先搭建一个RocketMQ的控制台。

前面提到过RocketMQ源码没有提供控制台,但是RcoektMQ的社区提供了一个控制台:
地址:控制台下载地址

下载完成后进入其中的rocket-console目录,使用maven进行编译(PS:需要自己安装mvn环境,这里不做说明,可自行百度)

使用名令:

mvn clean package -Dmaven.test.skip=true
复制代码

编译完成信息如下:

……
3 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/shared/maven-shared-utils/3.0.1/maven-shared-utils-3.0.1.jar (154 kB at 7.6 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/org/iq80/snappy/snappy/0.4/snappy-0.4.jar (58 kB at 2.7 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/3.0.24/plexus-utils-3.0.24.jar (247 kB at 8.3 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/maven-core/3.0/maven-core-3.0.jar (527 kB at 15 kB/s)
[INFO] Building jar: /root/javadevtools/rocketmq/rocketmq-externals-master/rocketmq-console/target/rocketmq-console-ng-1.0.1-sources.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  18:24 min
[INFO] Finished at: 2021-08-08T21:53:25+08:00
[INFO] ------------------------------------------------------------------------
复制代码

主要看到BUILD SUCCESS即可。然后在rocketmq-console目录下可以看到新生成一个target目录,里面有运行的jar包。

但是这个时候要注意,在这个项目的
application.properties中需要指定nameserver的地址。默认这个属性是空的。该配置文件在项目的resources下

rocketmq.config.namesrvAddr=192.168.40.131:9876;192.168.40.132:9876;192.168.40.133:9876
复制代码

然后执行:

java -jar rocketmq-console-ng-1.0.1.jar
复制代码

看到如下信息表示执行成功:
首先是JVM running表示成功,后面会显示节点的心跳连接信息:如下:

[2021-08-08 22:23:00.288]  INFO closeChannel: close the connection to remote address[192.168.40.132:9876] result: true
[2021-08-08 22:23:00.349]  INFO closeChannel: close the connection to remote address[192.168.40.132:11009] result: true
[2021-08-08 22:23:30.315]  INFO closeChannel: close the connection to remote address[192.168.40.133:10911] result: true
[2021-08-08 22:23:30.316]  INFO closeChannel: close the connection to remote address[192.168.40.132:9876] result: true
[2021-08-08 22:23:30.316]  INFO closeChannel: close the connection to remote address[192.168.40.132:11011] result: true
[2021-08-08 22:23:30.316]  INFO closeChannel: close the connection to remote address[192.168.40.132:10911] result: true
[2021-08-08 22:23:30.316]  INFO closeChannel: close the connection to remote address[192.168.40.133:10909] result: true
[2021-08-08 22:23:30.317]  INFO closeChannel: close the connection to remote address[192.168.40.133:11011] result: true
[2021-08-08 22:23:30.317]  INFO closeChannel: close the connection to remote address[192.168.40.132:10909] result: true
复制代码

然后在浏览器访问:ip+端口:

我的是:http://192.168.40.131:8080

可以看到如下界面:

image.png

比较直观的验证了上一章我们的集群是搭建成功了。

Dleger高可用集群搭建

主从结构只能做数据备份,并没有容灾功能。意味着当master节点挂掉后,slave节点是无法切换成master节点的。反之slave挂掉,对集群的影响不大。即当消费者要拉取的数据量很大的时候,RocketMQ有一定的机制会优先保证Master节点的性能,其他大部分数据会从slave拉取。所以slave挂掉,系统在大数据的冲击下,吞吐量会下降。

所以需要进行高可用的容灾备份,需要采用Dledger的方式来搭建高可用集群。注意,Dledger需要RocketMQ4.5以后的版本才支持。我使用的是4.7.1版本已经默认集成了dledger。

搭建方法

要搭建高可用的Broker集群,我们只需要配置conf/dleger下的配置文件即可。

这种模式是基于Raft协议的,是一个类似于zookeeper的paxos协议的选举协议,也是在集群中选举出一个leader,其他的就是follower。Raft协议基于休眠随机休眠机制的,选举过程会比paxos相对慢一些。

关于RocketMQ内存就不再赘述了,修改conf/dleger下的配置文件。与dleger相关的几个配置如下:

name 含义 举例
enableDLegerCommitLog 是否启动 DLedger true
dLegerGroup DLedger Raft Group的名字,建议和 brokerName 保持一致 RaftNode00
dLegerPeers DLedger Group 内各节点的端口信息,同一个 Group 内的各个节点配置必须要保证一致 n0-127.0.0.1:40911;n1-127.0.0.1:40912;n2-127.0.0.1:40913
dLegerSelfId 节点 id, 必须属于 dLegerPeers 中的一个;同 Group 内各个节要唯一 n0
sendMessageThreadPoolNums 发送线程个数,建议配置成 Cpu 核数 16

配置节点文件

服务器配置说明如下:

服务器名称 ip 服务器启动服务
dockerVm-》 主 192.168.40.131 nameServer、mqbroker、rocket-extern可视化服务
dockerVm2 -》从 192.168.40.132 nameServer、mqbroker
dockerVm3-》从 192.168.40.133 nameServer、broker

dockerVm配置

修改broker-n0.conf文件:配置如下

# 集群名
brokerClusterName = RaftCluster
# broker组名,同一个RaftClusterGroup内,brokerName名要一样
brokerName=RaftNode00
# 监听的端口
listenPort=30911
# 你设置的NameServer地址和端口
namesrvAddr=192.168.40.131:9876;192.168.40.132:9876;192.168.40.133:9876
# store存放目录
storePathRootDir=/tmp/rmqstore/node00
# commitlog存放目录
storePathCommitLog=/tmp/rmqstore/node00/commitlog
# 是否开启Dledger
enableDLegerCommitLog=true
# 组节点名称
dLegerGroup=RaftNode00
# n0 n1 n2 分别是broker1,broker2,broker3 的 dLegerSelfId
# 例如:dLegerPeers=n0-服务器1的IP:40911;n1-服务器2的IP:40912;n2-服务器3的IP:40913
dLegerPeers=n0-192.168.40.131:40911;n1-192.168.40.132:40912;n2-192.168.40.133:40913
## must be unique
## 这个值必须是在同一个RaftClusterGroup内唯一的
dLegerSelfId=n0
# 发送线程个数,建议配置成 Cpu 核数
sendMessageThreadPoolNums=1
## 如果虚拟机配置了多个网卡,所以会绑定ip错误,需要指定自己虚拟机的ip,没有的话不用管,我的就没有
## brokerIP1=192.168.40.131
复制代码

dockerVm2的配置

修改broker-n1.conf文件:配置如下

brokerClusterName = RaftCluster
brokerName=RaftNode00
listenPort=30921
namesrvAddr=192.168.40.131:9876;192.168.40.132:9876;192.168.40.133:9876
storePathRootDir=/tmp/rmqstore/node01
storePathCommitLog=/tmp/rmqstore/node01/commitlog
enableDLegerCommitLog=true
dLegerGroup=RaftNode00
dLegerPeers=n0-192.168.56.102:40911;n1-192.168.56.103:40912;n2-192.168.56.104:40913
## must be unique
dLegerSelfId=n1
sendMessageThreadPoolNums=1
## 如果虚拟机配置了多个网卡,所以会绑定ip错误,需要指定自己虚拟机的ip,没有的话不用管,我的就没有
## brokerIP1=192.168.40.132
复制代码

dockerVm3的配置

修改broker-n1.conf文件:配置如下

brokerClusterName = RaftCluster
brokerName=RaftNode00
listenPort=30931
namesrvAddr=192.168.40.131:9876;192.168.40.132:9876;192.168.40.133:9876
storePathRootDir=/tmp/rmqstore/node02
storePathCommitLog=/tmp/rmqstore/node02/commitlog
enableDLegerCommitLog=true
dLegerGroup=RaftNode00
dLegerPeers=n0-192.168.40.131:40911;n1-192.168.40.132:40912;n2-192.168.40.133:40913
## must be unique
dLegerSelfId=n2
sendMessageThreadPoolNums=1
## 如果虚拟机配置了多个网卡,所以会绑定ip错误,需要指定自己虚拟机的ip,没有的话不用管,我的就没有
## brokerIP1=192.168.40.133
复制代码

启动服务

1.首先启动dockerVm的nameServer和mqbroker、以及可视化服务

./mqnamesrv
./mqbroker -c ../conf/dledger/broker-n0.conf 
java -jar rocketmq-console-ng-1.0.1.jar
复制代码

2.接着启动dockerVm2的服务

./mqnamesrv
./mqbroker -c ../conf/dledger/broker-n1.conf 
复制代码

3.接着启动dockerVm3的服务

./mqnamesrv
./mqbroker -c ../conf/dledger/broker-n2.conf 
复制代码

全部启动后在网页查看cluster:

(PS: 此时应该是ip为192.168.40.131为主节点,但是我测试直接把主节点kill了,所以此时主节点经过删选变了)

image.png

从而也验证了集群的高可用。

(PS:在bin/dleger下有个fast-try.sh,这个脚本是在本地启动三个RocketMQ实例,搭建一个高可用的集群。读取的文件就是conf/dleger下的配置文件。但是要注意内存的配置。)

至此RocketMQ的集群搭建暂告一段落,其他的集群搭建方式与此类似,都是相关文件下的配置文件修改。不在赘述。不会的可以百度一波。教程都有。

调整系统参数

实际使用中,我们还需要根据实际的服务去调整RocketMQ的配置,这样才能让RocketMQ的优势发挥到最大。

这里以 runbroker.sh中对G1的配置举例:在runbroker.sh中的关键配置:

JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -
XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -
XX:SoftRefLRUPolicyMSPerMB=0"
JAVA_OPT="${JAVA_OPT} -verbose:gc -
Xloggc:${GC_LOG_DIR}/rmq_broker_gc_%p_%t.log -XX:+PrintGCDetails -
XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -
XX:+PrintAdaptiveSizePolicy"
JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -
XX:GCLogFileSize=30m"
复制代码

-XX:+UseG1GC:使用G1垃圾回收器;

-XX:G1HeapRegionSize=16m将G1的region块大小设为16m;

-XX:G1ReservePerCent: 在G1的老年代中预留了25%空闲内存,默认值是10%,RocketMQ把这个参数调大了;

-XX:InitiatingHeapOccupancyPercent=30:当堆内存的使用率达到30%就会启动G1垃圾收集器尝试回收垃圾,默认值是45%,RocketMQ把这个参数调小了,也就是提高了GC的频率,但是避免了垃圾对象过多,一次垃圾回收时间太长的问题;

RocketMQ的其他一些核心参数

sendMessageThreadPoolNums=16:默认值是16,表明Rocket内部使用的线程池数量是16个,其实这个参数可以根据机器的CPU核心进行适当调整。如果你的机器核心数量超过16个,就可以把参数适当调大。

Linux内核参数定制

ulimit:需要进行大量的网络通信和磁盘IO;

vm.extra_free_kbytes:告诉VM在后台回收(kswapd)启动的阈值与直接回收(通过分配进程)的阈值之间保留额外的可用内存。RocketMQ使用此参数来避免内存分配中的长延迟(与具体内核版本有关)

vm.min_free_kbytes,如果将其设置为低于1024KB,将会巧妙的将系统破坏,并且系统在高负载下容易出现死锁。

vm.max_map_count,限制一个进程可能具有的最大内存映射区域数。RocketMQ将使用mmap加载CommitLog和ConsumeQueue,因此建议将为此参数设置较大的值。

vm.swappiness,定义内核交换内存页面的积极程度。较高的值会增加攻击性,较低的值会减少交换量。建议将值设置为10来避免交换延迟。

File descriptor limits,RocketMQ需要为文件(CommitLog和ConsumeQueue)和网络连接打开文件描述符。我们建议设置文件描述符的值为655350。

PS: 这些参数在CentOS7中的配置文件都在 /proc/sys/vm目录下。
另外,RocketMQ的bin目录下有个os.sh里面设置了RocketMQ建议的系统内核参数,可以根据情况进行调整。