RocketMQ学习教程:04.集群搭建【云图智联】

本文首先会对rocketmq集群四种部署模式进行介绍,包括:单主模式,多master模式,多master多slave模式异步复制,多master多slave模式同步复制,对比各种模式的优缺点。接着将每一种模式部署成一个集群,因此总共有4个集群,由一个NameServer集群进行管理。最后会介绍常见部署错误问题的解决方案。

1 部署模式介绍

一个完整的RocketMQ集群由NameServer集群,Broker集群,Producer集群,Consumer集群组成。本节主要介绍NameServer集群,Broker集群的搭建。

一个NameServer集群可以管理多个Broker集群,每个Broker集群由多组broker复制组构成,多个broker复制组通过指定相同的集群名称,来构成一个Broker集群。

具体来说,每个broker复制组都满足以下几点:

  • 包含一个master节点,零个或者多个slave节点,且这些节点需要指定相同的broker名称;不同的broker复制组的broker名称必须不同。

  • master和slave通过brokerId参数进行区分。master的 brokerId参数必须是 0,slave 的 brokerId 必须是大于0的整数,如果有多个slave,这些slave的brokerId需要指定为不同的值。

  • master可读可写,slave只可以读,master通过主从复制的方式将数据同步给slave,支持同步复制和异步复制两种复制方式,目前master宕机后,slave不能自动切换为master。

基于Broker复制组的特性,一个Broker集群通常有多种部署方式:

1. 单个 Master 

        集群中只有一个broker复制组,且只包含一个master节点。这种方式部署风险较大,一旦 Broker 重启或者宕机时,会导致整个服务不可用,通常是开发调试时使用,不建议线上环境使用 

2. 多 Master 模式 

        集群中有多个broker复制组,且都只有master节点,没有slave节点。例如 2 个 master 或者 3 个 master节点。

        优点: 配置简单,单个 Master 宕机或重启维护对应用无影响,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢)。性能最高。 

        缺点: 单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到影响。 

3 多 Master 多 Slave 模式,异步复制 

        集群中有多个broker复制组,且每个复制组都有master节点,也有slave节点。例如:每个 master 配置一个 slave。HA 采用异步复制方式,主备有短暂消息延迟,毫秒级。 

        优点: 即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,因为 Master 宕机后,消费者仍然可以 从 Slave 消费,此过程对应用透明。不需要人工干预。性能同多 Master 模式几乎一样。 

        缺点:Master 宕机,磁盘损坏情况,会丢失少量消息。

4. 多 Master 多 Slave 模式,同步复制 

        与第三种方式类似,不同的是,HA 采用同步复制,生产者发送发送消息时,只有再主备都写成功,才向应用返回成功。 

        优点: 数据与服务都无单点,Master 宕机情况下,消息无延迟,服务可用性与数据可用性都非常高     

        缺点: 性能比异步复制模式略低,大约低 10%左右,发送单个消息的 RT 会略高。

接下来,笔者将将演示在Linux操作系统中如何搭建一个单节点NameServer集群,以及上述四种Broker集群,并由这个单节点的NameServer集群来管理这四个Broker集群。

注意:在实际生产环境中,NameServer以及每个Broker节点(不管是master还是slave),都是部署在不同的机器上的。这里简单起见,将通过伪分布式的方式进行搭建,即所有节点都运行在一台机器上。如果读者希望搭建完整的分布式集群,可以使用vmvare/virtualbox等工具,只需要将本文的配置拷贝即可。

 

2 前提条件

wRocketMQ NameServer和Broker是基于Java 开发的,需要安装JDK,且需要保证二者版本的匹配。下图列出安装/运行RocketMQ需要的JDK版本。

Version Client Broker NameServer
4.0.0-incubating >=1.7 >=1.8 >=1.8
4.1.0-incubating >=1.6 >=1.8 >=1.8
4.2.0 >=1.6 >=1.8 >=1.8
4.3.x >=1.6 >=1.8 >=1.8
4.4.x >=1.6 >=1.8 >=1.8
4.5.x >=1.6 >=1.8 >=1.8
4.6.x >=1.6 >=1.8 >=1.8

本文以RocketMQ 4.6.0版本为例进行讲解,对应JDK版本为1.8。本文不讲解JDK如何安装,读者可自行查阅相关资料。确保JDK的版本>=1.8,可以通过如下方式验证:

  1. $ java -version
  2. java version "1.8.0_131"
  3. Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
  4. Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode

 

3 下载安装

下载

该地址列出了RocketMQ所有发布的版本:https://github.com/apache/rocketmq/releases

这里将RocketMQ安装到Linux文件系统的/opt目录,首先进入/opt目录

  1. cd /opt

可以直接从github下载,但是网速较慢

  1. $ wget https://github.com/apache/rocketmq/archive/rocketmq-all-4.6.0.zip

网速慢的同学也可以从国内镜像下载:

  1. $ wget https://mirrors.tuna.tsinghua.edu.cn/apache/rocketmq/4.6.0/rocketmq-all-4.6.0-bin-release.zip

下载之后进行解压缩:

  1. $ unzip rocketmq-all-4.6.0-bin-release.zip

解压目录说明

  1. rocketmq-all-4.6.0-bin-release
  2. ├── benchmark #性能测试脚本
  3. ├── bin       #命令行工具
  4. ├── conf      #配置文件目录
  5. ├── lib       #依赖的第三方类库
  6. ├── LICENSE
  7. ├── NOTICE
  8. └── README.md

设置ROKCKET_HOME环境变量:

在这里,将我们将RocketMQ安装包的解压目录设置为ROCKETMQ_HOME环境变量。例如笔者的解压目录为:

  1. $ pwd
  2. /opt/rocketmq-all-4.6.0-bin-release

为了以后升级方便,我们创建一个软连接:

  1. sudo ln -s /opt/rocketmq-all-4.6.0-bin-release rocketmq

修改/etc/profile,添加以下一行:

  1. export ROCKETMQ_HOME=/opt/rocketmq

执行以下命令,使得环境变量生效

  1. source /etc/profile

验证环境变量生效:

  1. $ echo $ROCKETMQ_HOME
  2. /opt/rocketmq

 

3.1 启动NameServer

启动

  1. $ nohup sh bin/mqnamesrv &

验证启动成功

  1. $ jps -l
  2. 3961157 sun.tools.jps.Jps
  3. 3953057 org.apache.rocketmq.namesrv.NamesrvStartup #NameServer进程

NameServer默认监听9876端口,也可以通过如下方式验证:

  1. $ lsof -iTCP -nP | grep 9876
  2. java    3953057 tianshouzhi.robin   65u  IPv6 134849198      0t0  TCP *:9876 (LISTEN)

设置NAMESRV_ADDR环境变量,修改etc/profile,添加以下内容:

  1. export NAMESRV_ADDR=localhost:9876

并执行"source /etc/profile"使得其生效

3.2 启动Broker

        ${ROCKETMQ_HOME}/conf目录下,提供了我们讲解到的RocketMQ四种部署模式的demo配置文件,如下所示:

  1. conf
  2. ├── 2m-2s-async                   //多Master多Slave模式,异步复制
  3. │   ├── broker-a.properties
  4. │   ├── broker-a-s.properties
  5. │   ├── broker-b.properties
  6. │   └── broker-b-s.properties
  7. ├── 2m-2s-sync                    //多Master多Slave 模式,同步复制
  8. │   ├── broker-a.properties
  9. │   ├── broker-a-s.properties
  10. │   ├── broker-b.properties
  11. │   └── broker-b-s.properties
  12. ├── 2m-noslave                    //多Master模式
  13. │   ├── broker-a.properties
  14. │   ├── broker-b.properties
  15. │   └── broker-trace.properties
  16. └── broker.conf                   //单Master模式

在实际生产环境中,你可以选择其中一种模式进行部署。从学习的角度,笔者将详细讲解每一种模式,每种模式部署为一个集群,因此总共会部署4个集群。

      另外,生产环境中至少需要部署为双主模式,每个机器只会部署一个broker,因此只使用broker.conf配置文件即可,根据要配置的节点的类型,将其他模式下的配置复制到broker.conf,或者直接修改broker.conf。

 

3.2.1 单Master模式

修改配置文件:

单master模式可以使用conf目录下的broker.conf 配置文件,内容如下所示:

  1. #集群名称
  2. brokerClusterName=single-master
  3. #broker复制组名称
  4. brokerName=broker-a
  5. #nameserver地址
  6. namesrvAddr=127.0.0.1:9876
  7. #brokerId,因为是master节点,所以这里设置为0
  8. brokerId=0
  9. #监听端口
  10. listenPort=10911
  11. #rocketmq定时清除
  12. deleteWhen=04
  13. #文件保留时间,默认48小时
  14. fileReservedTime=48
  15. #broker角色,异步复制
  16. brokerRole=ASYNC_MASTER
  17. #异步刷盘
  18. flushDiskType=ASYNC_FLUSH
  19. #存储目录
  20. storePathRootDir=/data/rocketmq/single-master/broker-a/store
  21. storePathCommitLog=/data/rocketmq/single-master/broker-a/store/commitlog

     注意:如果配置项名称或者值写错,broker启动时并不会报错,会使用默认值替代,常见错误:如在=号两边加了空格,这里是不需要的。

     启动通过bin目录下的mqbroker脚本。由于默认的配置,启动后会立即占用8G内存,如果机器内存不够,可以修改bin/runbroker.sh,找到以下这一行:

  1. JAVA_OPT="${JAVA_OPT} -server -Xms8g -Xmx8g -Xmn4g"

将其修改为:

  1. JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn1g"

启动:

  1. $ nohup sh bin/mqbroker -c conf/broker.conf &

注意:broker启动时不会读取broker.conf中的配置,尽管也可以启动,但是如果需要使得配置文件生效,必须通过-c参数进行指定。

验证启动成功:

  1. $ jps -l
  2. 3961157 sun.tools.jps.Jps
  3. 3960977 org.apache.rocketmq.broker.BrokerStartup
  4. 3953057 org.apache.rocketmq.namesrv.NamesrvStartup

NameServer默认监听在10911端口,也可以通过以下方式验证:

  1. $ lsof -iTCP -nP | grep 10911
  2. java    37686 tianshouzhi.robin  107u  IPv6 137040246      0t0  TCP *:10911 (LISTEN)

如果启动失败,可以通过以下命令查看错误的具体信息:

  1. tail -200f ~/logs/rocketmqlogs/broker.log

 

测试发送/消费消息

安装包bin目录下提供了一个tools.sh工具,我们可以通过其来测试发送/接收消息。

测试发送消息:

执行以下命令将会往一个名为TopicTest主题中发送1000条消息

  1. $ sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer 
  2. SendResult [sendStatus=SEND_OK, msgId=FDBDDC0300FF00010001022700120225003C3D4EAC696720298203E7, 
  3. offsetMsgId=AC11000100002A9F0000000000037567, 
  4. messageQueue=MessageQueue [topic=TopicTest, brokerName=broker-a, queueId=3], 
  5. wqueueOffset=249]
  6. ...

测试消费消息:

执行以下命令,将会之前的消费1000条消息

  1. $ sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer
  2. ConsumeMessageThread_%d Receive New Messages: [MessageExt… 
  3. ...

这里我们是通过命令行工具来发送/消费消息,在后文中,我们将介绍如何通过API的方式来完成相同的功能。

 

查看集群列表信息:

  1. $ sh bin/mqadmin clusterList -n localhost:9876
  2. #Cluster Name    #Broker Name   #BID        #Addr           #Version   #...(略)
  3. single-master    broker-a      0        192.168.1.3:10911     V4_6_0    …

输出的每一列说明如下:

  • Cluster Name:集群的名称,即brokerClusterName配置项的值

  • Broker Name:Broker的名称,即brokerName配置项的值

  • BID:Broker的ID,这里显示为0,即brokerId配置项的值

  • Addr:监听的IP/端口,供生产者/消费者访问,端口即listenPort配置项的值

  • Version:broker的版本

 

3.2.2 多Master模式

这里演示的多master模式是双主模式:包含2个master节点,没有slave节点。如前所属,这里是伪分布式,在一台机器上启动两个master节点。我们需要对conf/2m-noslave目录下的2个配置文件进行一些修改,否则会与前面搭建的单master模式存在一些冲突,如监听的端口和保存数据的路径等。

修改后的结果如下所示:

conf/2m-noslave/broker-a.properties

  1. brokerClusterName=2m-noslave
  2. listenPort=11911
  3. namesrvAddr=127.0.0.1:9876
  4. brokerName=2m-broker-a
  5. brokerId=0
  6. deleteWhen=04
  7. fileReservedTime=48
  8. brokerRole=ASYNC_MASTER
  9. flushDiskType=ASYNC_FLUSH
  10. storePathRootDir=/data/rocketmq/2m-noslave/broker-a/store/
  11. storePathCommitLog=/data/rocketmq/2m-noslave/broker-a/store/commitlog/
  12. storePathConsumerQueue=/data/rocketmq/2m-noslave/broker-a/store/consumequeue/

conf/2m-noslave/broker-b.properties

  1. brokerClusterName=2m-noslave
  2. listenPort=12911
  3. namesrvAddr=127.0.0.1:9876
  4. brokerName=2m-broker-b
  5. brokerId=0
  6. deleteWhen=04
  7. fileReservedTime=48
  8. brokerRole=ASYNC_MASTER
  9. flushDiskType=ASYNC_FLUSH
  10. storePathRootDir=/data/rocketmq/2m-noslave/broker-b/store/
  11. storePathCommitLog=/data/rocketmq/2m-noslave/broker-b/store/commitlog/
  12. storePathConsumerQueue=/data/rocketmq/2m-noslave/broker-b/store/consumequeue/

在这里,我们将两个配置文件中的brokerClusterName都改成了2m-noslave,表名这两个broker节点将组成一个新的集群。也别修改了listenPort配置项以监听不同的端口,此外,我们修改了三个storePath前缀的配置项,将数据存储到不同的目录中。

特别需要注意的是:一些同学可能认为brokerClusterName已经不同了,没有必要修改brokerName配置项,这是一种误解。在RocketMQ中,一个NameServer集群可以多个Broker集群,但是broker集群的名称并没有起到命名空间的作用,因此管理的所有Broker集群下的broker复制组的名称都不能相同。

启动broker-a

  1. nohup sh bin/mqbroker -c conf/2m-noslave/broker-a.properties &

启动broker-b

  1. nohup sh bin/mqbroker -c conf/2m-noslave/broker-b.properties &

在启动之后,当我们在查看集群列表信息时,如下:

  1. $ sh bin/mqadmin clusterList -n localhost:9876
  2. #Cluster Name     #Broker Name     #BID  #Addr               #Version
  3. single-master     broker-a          0     192.168.1.3:10911   V4_6_0  
  4. 2m-noslave        2m-broker-a       0     192.168.1.3:11911   V4_6_0  
  5. 2m-noslave        2m-broker-b       0     192.168.1.3:12911   V4_6_0

这里显示了2个broker集群:single-master和2m-noslave,其中后者存在两个节点。

 

3.2.3 多 Master 多 Slave 模式,异步复制 

该模式需要使用conf/2m-2s-async目录下的四个配置文件。同样我们需要修改brokerClusterName,listenPort,brokerName以及存储路径。特别需要注意的是对于slave,其brokerRole配置项需要为SLAVE,brokerId是需要时一个大于0的值。

修改后的结果如下所示:

conf/2m-2s-async/broker-a.properties

  1. brokerClusterName=2m-2s-async
  2. listenPort=13911
  3. namesrvAddr=127.0.0.1:9876
  4. brokerName=2m-2s-async-broker-a
  5. brokerId=0
  6. deleteWhen=04
  7. fileReservedTime=48
  8. brokerRole=ASYNC_MASTER
  9. flushDiskType=ASYNC_FLUSH
  10. storePathRootDir=/data/rocketmq/2m-2s-async/broker-a-0/store/
  11. storePathCommitLog=/data/rocketmq/2m-2s-async/broker-a-0/store/commitlog/
  12. storePathConsumerQueue=/data/rocketmq/2m-2s-async/broker-a-0/store/consumequeue/

conf/2m-2s-async/broker-a-s.properties

  1. brokerClusterName=2m-2s-async
  2. listenPort=14911
  3. namesrvAddr=127.0.0.1:9876
  4. brokerName=2m-2s-async-broker-a
  5. brokerId=1
  6. deleteWhen=04
  7. fileReservedTime=48
  8. brokerRole=SLAVE
  9. flushDiskType=ASYNC_FLUSH
  10. storePathRootDir=/data/rocketmq/2m-2s-async/broker-a-1/store/
  11. storePathCommitLog=/data/rocketmq/2m-2s-async/broker-a-1/store/commitlog/
  12. storePathConsumerQueue=/data/rocketmq/2m-2s-async/broker-a-1/store/consumequeue/

conf/2m-2s-async/broker-b.properties

  1. brokerClusterName=2m-2s-async
  2. listenPort=15911
  3. namesrvAddr=127.0.0.1:9876
  4. brokerName=2m-2s-async-broker-b
  5. brokerId=0
  6. deleteWhen=04
  7. fileReservedTime=48
  8. brokerRole=ASYNC_MASTER
  9. flushDiskType=ASYNC_FLUSH
  10. storePathRootDir=/data/rocketmq/2m-2s-async/broker-b-0/store/
  11. storePathCommitLog=/data/rocketmq/2m-2s-async/broker-b-0/store/commitlog/
  12. storePathConsumerQueue=/data/rocketmq/2m-2s-async/broker-b-0/store/consumequeue/

conf/2m-2s-async/broker-b-s.properties

  1. brokerClusterName=2m-2s-async
  2. listenPort=16911
  3. namesrvAddr=127.0.0.1:9876
  4. brokerName=2m-2s-async-broker-b
  5. brokerId=1
  6. deleteWhen=04
  7. fileReservedTime=48
  8. brokerRole=SLAVE
  9. flushDiskType=ASYNC_FLUSH
  10. storePathRootDir=/data/rocketmq/2m-2s-async/broker-b-1/store/
  11. storePathCommitLog=/data/rocketmq/2m-2s-async/broker-b-1/store/commitlog/
  12. storePathConsumerQueue=/data/rocketmq/2m-2s-async/broker-b-1/store/consumequeue/

依次启动:

  1. nohup sh bin/mqbroker -c conf/2m-2s-async/broker-a.properties &
  2. nohup sh bin/mqbroker -c conf/2m-2s-async/broker-a-s.properties &
  3. nohup sh bin/mqbroker -c conf/2m-2s-async/broker-b.properties &
  4. nohup sh bin/mqbroker -c conf/2m-2s-async/broker-b-s.properties &

查看集群信息:

  1. $ sh bin/mqadmin clusterList -n localhost:9876
  2. #Cluster Name     #Broker Name            #BID  #Addr                  #Version
  3. single-master     broker-a                0     172.17.0.1:10911       V4_6_0   
  4. 2m-2s-async       2m-2s-async-broker-a    0     172.17.0.1:13911       V4_6_0   
  5. 2m-2s-async       2m-2s-async-broker-a    1     172.17.0.1:14911       V4_6_0   
  6. 2m-2s-async       2m-2s-async-broker-b    0     172.17.0.1:15911       V4_6_0   
  7. 2m-2s-async       2m-2s-async-broker-b    1     172.17.0.1:16911       V4_6_0   
  8. 2m-noslave        2m-broker-a             0     172.17.0.1:11911       V4_6_0   
  9. 2m-noslave        2m-broker-b             0     172.17.0.1:12911       V4_6_0

这里多出了2m-2s-async集群的四个broker节点信息。

 

3.2.4 多 Master 多 Slave 模式,同步复制 

        该模式需要使用conf/2m-2s-sync目录下的四个配置文件,与异步复制最大的不同是,需要将master节点的brokerRole配置项需要改为SYNC_MASTER。这里不再赘述。如果是在同一台机器上搭建此模式,记得修对应的参数。

 

3.3 停止

bin目录安装包下有一个mqshutdown脚本,其既可以关闭Broker,也可以关闭NameServer。注意该脚本会将本机上启动的所有Broker或所有NameServer关闭。

停止broker

  1. $ sh bin/mqshutdown broker
  2. The mqbroker(67521
  3. 74023
  4. 74153
  5. 362837
  6. 362958
  7. 363070) is running...
  8. Send shutdown request to mqbroker(67521
  9. 74023
  10. 74153
  11. 362837
  12. 362958
  13. 363070)

停止nameserver

  1. $ sh bin/mqshutdown namesrv
  2. The mqnamesrv(3953057) is running...
  3. Send shutdown request to mqnamesrv(3953057) OK

 

4  常见安装错误

错误1:端口已被占用

  1. java.net.BindException: Address already in use
  2.         at sun.nio.ch.Net.bind0(Native Method)
  3.         at sun.nio.ch.Net.bind(Net.java:433)
  4.         at sun.nio.ch.Net.bind(Net.java:425)
  5.         at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
  6.         at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
  7.         at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:67)
  8.         at

原因:重复监听了同一个端口,通常是对同一个配置文件启动了多次,或者配置listenPort端口未生效。

错误2:MQ已启动

  1. java.lang.RuntimeException: Lock failed,MQ already started
  2.         at org.apache.rocketmq.store.DefaultMessageStore.start(DefaultMessageStore.java:222)
  3.         at org.apache.rocketmq.broker.BrokerController.start(BrokerController.java:853)
  4.         at org.apache.rocketmq.broker.BrokerStartup.start(BrokerStartup.java:64)
  5.         at org.apache.rocketmq.broker.BrokerStartup.main(BrokerStartup.java:58)

原因:多个配置文件中,可能指定了相同的存储路径,检查配置是否正确。

错误3:配置文件不存在

  1. java.io.FileNotFoundException: conf/2m-2s-async/broker-a-m.properties (No such file or directory)
  2.         at java.io.FileInputStream.open0(Native Method)
  3.         at java.io.FileInputStream.open(FileInputStream.java:195)
  4.         at java.io.FileInputStream.(FileInputStream.java:138)
  5.         at java.io.FileInputStream.(FileInputStream.java:93)
  6.         at org.apache.rocketmq.broker.BrokerStartup.createBrokerController(BrokerStartup.java:128)
  7.         at org.apache.rocketmq.broker.BrokerStartup.main(BrokerStartup.java:58)

配置文件不存在,检查对应目录下是否有此文件

错误4:内存分配失败

未按照前文所属修改bin/runserver.sh,bin/runbroker.sh脚本,导致启动每一个节点时占用内存过多。如果本身机器内存就不足,可以不必同时运行这么多模式。

免费学习视频欢迎关注云图智联:https://e.yuntuzhilian.com/

你可能感兴趣的:(MQ)