• rocketmq那些事儿之集群环境搭建


    上一篇入门基础部分对rocketmq进行了一个基础知识的讲解说明,在正式使用前我们需要进行环境的搭建,今天就来说一说rockeketmq分布式集群环境的搭建

    前言

    之前已经介绍了rocketmq的入门基础,相信各位已经基本了解,今天进行一个分布式集群的搭建,其实可以通过本地源码来进行源码的使用和学习,但是作为开发维护人员还是需要去了解分布式集群的部署流程,方便后面集群的调试和测试

    配置参数

    注意官方给的配置文件都是默认的,最简单的版本,线上的环境需要根据自己需求来进行配置,在这里说明下其中的部分配置参数:

    #所属集群名字
    brokerClusterName=rocketmq‐cluster
    #broker名字,注意此处不同的配置文件填写的不一样
    brokerName=broker‐a
    #0 表示 Master,>0 表示 Slave
    brokerId=0
    #nameServer地址,分号分割
    namesrvAddr=rocketmq1:9876;rocketmq2:9876
    #在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
    defaultTopicQueueNums=4
    #是否允许 Broker 自动创建Topic,建议线上关闭
    autoCreateTopicEnable=true
    #是否允许 Broker 自动创建订阅组,建议线上关闭
    autoCreateSubscriptionGroup=true
    #Broker 对外服务的监听端口
    listenPort=10911
    #删除文件时间点,默认凌晨 4点
    deleteWhen=04
    #文件保留时间,默认 72 小时
    fileReservedTime=72
    #commitLog每个文件的大小默认1G
    mapedFileSizeCommitLog=1073741824
    #ConsumeQueue每个文件默认存30W条,根据业务情况调整
    mapedFileSizeConsumeQueue=300000
    #检测物理文件磁盘空间
    diskMaxUsedSpaceRatio=75
    #存储路径
    storePathRootDir=/root/rocketmq/store
    #commitLog 存储路径
    storePathCommitLog=/root/rocketmq/store/commitlog
    #消费队列存储路径
    storePathConsumeQueue=/root/rocketmq/store/consumequeue
    #消息索引存储路径
    storePathIndex=/root/rocketmq/store/index
    #checkpoint 文件存储路径
    storeCheckpoint=/root/rocketmq/store/checkpoint
    #abort 文件存储路径
    abortFile=/root/rocketmq/store/abort
    #限制的消息大小 默认4M
    #maxMessageSize=4194304
    #Broker 的角色
    #‐ ASYNC_MASTER 异步复制Master
    #‐ SYNC_MASTER 同步双写Master
    #‐ SLAVE
    brokerRole=SYNC_MASTER
    

    集群类型

    搭建说明官方地址:https://github.com/apache/rocketmq/tree/master/docs/cn/operation.md

    单机版本根据官方部署即可,这里不再介绍,今天主要说明下如何搭建分布式集群,由于公司环境使用的就是同步双写模式,今天就以这个模式为例来进行搭建

    接下来以搭建双Master双Slave模式-同步双写异步刷盘集群为例进行说明

    环境准备

    这里因为笔者只能在本地进行(测试环境机器不够了。。。),所以使用了2台虚拟机环境,这里用的是VMware启动了2台centos7环境,首先需要提醒的是我们可以先部署一台,另一台直接克隆修改些参数就可以构建完成了,所以先进行一台的部署,如果是物理机环境,直接把源码拷贝下修改参数部署即可

    整个集群环境是这样的:

    • 机器A: 1 namesrv + 1 broker-master-a + 1 broker-slave-b
    • 机器B: 1 namesrv + 1 broker-master-b + 1 broker-slave-a

    部署上可以看到我们是用了2台机器互为主备,因为本地不能搞太多,当然,公司测试环境资源不够的话同样可以这样搭建

    同时为了集群生产消费观察的便捷,我们还需要一个console,为了部署的方便(因为我懒得再进行下载编译配置参数这套了),我们直接使用docker来部署console,这部分后面会说

    搭建流程

    在正式搭建前,我们需要在centos7中安装好需要的基础环境:

    • jdk8
    • maven
    • 固定ip

    虚拟机固定ip可参考这个地址进行设置:https://segmentfault.com/a/1190000017535131

    这里我们一定要注意,先搭建机器A上的集群环境!直接克隆修改些参数就能构建完成,不要多做无用工作,当然,这里只是基于本地虚拟机环境,线上环境复制下整个项目源码到另一台机器上部署就好

    配置完成之后,我本地虚拟机机器地址为:

    机器A IP: 192.168.211.11
    机器B IP: 192.168.211.12 (这个A部署完成后再克隆配置)

    下载编译

    wget https://archive.apache.org/dist/rocketmq/4.5.2/rocketmq-all-4.5.2-source-release.zip
    unzip rocketmq-all-4.5.2-source-release.zip
    cd rocketmq-all-4.5.2-source-release
    mvn -Prelease-all -DskipTests clean install -U
    cd distribution/target/rocketmq-4.5.2
    

    下载编译

    目录下就是编译完成的文件,接下来我们就通过这个进行集群环境部署

    DNS修改

    修改/etc/hosts文件添加如下地址,为了配置的方便,我们修改虚拟机的本地DNS,便于配置文件的操作

    192.168.211.11 rocketmq1
    192.168.211.12 rocketmq2
    

    broker配置文件

    在正式启动前我们需要先将集群环境需要的配置文件配置好,根据官网说明我们需要修改部分参数,这里我们直接修改conf/2m‐2s‐sync目录下的配置文件来完成

    broker-a.properties文件内容修改如下:

    brokerClusterName=DefaultCluster
    brokerName=broker-a
    brokerId=0
    deleteWhen=04
    fileReservedTime=48
    brokerRole=SYNC_MASTER
    flushDiskType=ASYNC_FLUSH
    #nameServer地址,分号分割
    namesrvAddr=rocketmq1:9876;rocketmq2:9876
    #Broker 对外服务的监听端口
    listenPort=10911
    #存储路径
    storePathRootDir=/root/rocketmq-m/store
    #commitLog 存储路径
    storePathCommitLog=/root/rocketmq-m/store/commitlog
    #消费队列存储路径存储路径
    storePathConsumeQueue=/root/rocketmq-m/store/consumequeue
    #消息索引存储路径
    storePathIndex=/root/rocketmq-m/store/index
    #checkpoint 文件存储路径
    storeCheckpoint=/root/rocketmq-m/store/checkpoint
    #abort 文件存储路径
    abortFile=/root/rocketmq-m/store/abort
    

    broker-a-s.properties文件内容修改如下:

    brokerClusterName=DefaultCluster
    brokerName=broker-a
    brokerId=1
    deleteWhen=04
    fileReservedTime=48
    brokerRole=SLAVE
    flushDiskType=ASYNC_FLUSH
    #nameServer地址,分号分割
    namesrvAddr=rocketmq1:9876;rocketmq2:9876
    #Broker 对外服务的监听端口
    listenPort=11911
    #存储路径
    storePathRootDir=/root/rocketmq-s/store
    #commitLog 存储路径
    storePathCommitLog=/root/rocketmq-s/store/commitlog
    #消费队列存储路径存储路径
    storePathConsumeQueue=/root/rocketmq-s/store/consumequeue
    #消息索引存储路径
    storePathIndex=/root/rocketmq-s/store/index
    #checkpoint 文件存储路径
    storeCheckpoint=/root/rocketmq-s/store/checkpoint
    #abort 文件存储路径
    abortFile=/root/rocketmq-s/store/abort
    

    broker-b.properties文件内容修改如下:

    brokerClusterName=DefaultCluster
    brokerName=broker-b
    brokerId=0
    deleteWhen=04
    fileReservedTime=48
    brokerRole=SYNC_MASTER
    flushDiskType=ASYNC_FLUSH
    #nameServer地址,分号分割
    namesrvAddr=rocketmq1:9876;rocketmq2:9876
    #Broker 对外服务的监听端口
    listenPort=10911
    #存储路径
    storePathRootDir=/root/rocketmq-m/store
    #commitLog 存储路径
    storePathCommitLog=/root/rocketmq-m/store/commitlog
    #消费队列存储路径存储路径
    storePathConsumeQueue=/root/rocketmq-m/store/consumequeue
    #消息索引存储路径
    storePathIndex=/root/rocketmq-m/store/index
    #checkpoint 文件存储路径
    storeCheckpoint=/root/rocketmq-m/store/checkpoint
    #abort 文件存储路径
    abortFile=/root/rocketmq-m/store/abort
    

    broker-b-s.properties文件内容修改如下:

    brokerClusterName=DefaultCluster
    brokerName=broker-b
    brokerId=1
    deleteWhen=04
    fileReservedTime=48
    brokerRole=SLAVE
    flushDiskType=ASYNC_FLUSH
    #nameServer地址,分号分割
    namesrvAddr=rocketmq1:9876;rocketmq2:9876
    #Broker 对外服务的监听端口
    listenPort=11911
    #存储路径
    storePathRootDir=/root/rocketmq-s/store
    #commitLog 存储路径
    storePathCommitLog=/root/rocketmq-s/store/commitlog
    #消费队列存储路径存储路径
    storePathConsumeQueue=/root/rocketmq-s/store/consumequeue
    #消息索引存储路径
    storePathIndex=/root/rocketmq-s/store/index
    #checkpoint 文件存储路径
    storeCheckpoint=/root/rocketmq-s/store/checkpoint
    #abort 文件存储路径
    abortFile=/root/rocketmq-s/store/abort
    

    brokerName,brokerId和brokerRole的不同使得同一套代码通过不同的配置文件启动作为集群中不同的角色,这里因为我们一台机器上部署了2个broker,所以文件存储路径要区分开来

    将编译修改完的文件拷贝放到/root/rocketmqbuild/namesrv,/root/rocketmqbuild/rocketmq-m(主broker)和/root/rocketmqbuild/rocketmq-s(备broker)中,方便执行,文件内容如下:

    [root@rocketmq1 rocketmqbuild]# tree -L 2
    .
    ├── namesrv
    │   ├── benchmark
    │   ├── bin
    │   ├── conf
    │   ├── lib
    │   ├── LICENSE
    │   ├── NOTICE
    │   └── README.md
    ├── rocketmq-m
    │   ├── benchmark
    │   ├── bin
    │   ├── conf
    │   ├── lib
    │   ├── LICENSE
    │   ├── NOTICE
    │   └── README.md
    └── rocketmq-s
        ├── benchmark
        ├── bin
        ├── conf
        ├── lib
        ├── LICENSE
        ├── NOTICE
        └── README.md
    

    日志配置

    上面完成之后,我们需要注意conf中的logback.*.xml配置文件中${user.home}需要替换为自己指定的目录,否则默认日志地址,这里为了方便,我们将其和store文件放在同一个父级文件夹下,通过sed进行替换:

    cd /root/rocketmqbuild/namesrv/conf
    sed -i 's#${user.home}#/root/namesrv#g' logback_namesrv.xml
    
    cd /root/rocketmqbuild/rocketmq-m/conf
    sed -i 's#${user.home}#/root/rocketmq-m#g' logback_broker.xml
    
    cd /root/rocketmqbuild/rocketmq-s/conf
    sed -i 's#${user.home}#/root/rocketmq-s#g' logback_broker.xml
    

    jvm参数配置

    修改完日志配置还要进行jvm参数的设置,之前的文章中脚本部分我已经说明过了,这里根据个人需求进行设置,因为在本地,设置小点

    #/root/rocketmqbuild/namesrv/bin/runserver.sh
    -server -Xms200m -Xmx200m -Xmn60m -XX:MetaspaceSize=40m -XX:MaxMetaspaceSize=80m
    #/root/rocketmqbuild/rocketmq-m/bin/runbroker.sh
    -server -Xms500m -Xmx500m -Xmn200m
    #/root/rocketmqbuild/rocketmq-s/bin/runbroker.sh
    -server -Xms500m -Xmx500m -Xmn200m
    

    A机器-NameServer

    整个集群环境需要先启动NameServer,命令如下:

    nohup sh /root/rocketmqbuild/namesrv/bin/mqnamesrv &

    查看日志是否成功

    tail -f /root/namesrv/logs/rocketmqlogs/namesrv.log

    2019-12-01 16:39:30 INFO main - tls.client.keyPassword = null
    2019-12-01 16:39:30 INFO main - tls.client.certPath = null
    2019-12-01 16:39:30 INFO main - tls.client.authServer = false
    2019-12-01 16:39:30 INFO main - tls.client.trustCertPath = null
    2019-12-01 16:39:31 INFO main - Using OpenSSL provider
    2019-12-01 16:39:32 INFO main - SSLContext created for server
    2019-12-01 16:39:32 INFO main - Try to start service thread:FileWatchService started:false lastThread:null
    2019-12-01 16:39:32 INFO NettyEventExecutor - NettyEventExecutor service started
    2019-12-01 16:39:32 INFO main - The Name Server boot success. serializeType=JSON
    2019-12-01 16:39:32 INFO FileWatchService - FileWatchService service started
    

    ok,成功

    A机器-broker-a-master

    启动broker-a的master,命令如下:

    nohup sh /root/rocketmqbuild/rocketmq-m/bin/mqbroker ‐c /root/rocketmqbuild/rocketmq-m/conf/2m‐2s‐sync/broker‐a.properties >/dev/null 2>&1 &

    查看启动日志:

    tail -f /root/rocketmq-m/logs/rocketmqlogs/broker.log

    2019-12-01 18:06:47 INFO brokerOutApi_thread_2 - register broker[0]to name server rocketmq1:9876 OK
    2019-12-01 18:06:48 WARN brokerOutApi_thread_1 - registerBroker Exception, rocketmq2:9876
    

    ok,连接上了本机的namesrv,但是另一个报错,没事,因为另一个还未启动,启动之后会重试,同时在日志中确认下配置参数是否生效了,broker启动成功

    A机器-broker-b-slave

    启动broker-b的slave,命令如下:

    nohup sh /root/rocketmqbuild/rocketmq-s/bin/mqbroker -c /root/rocketmqbuild/rocketmq-s/conf/2m-2s-sync/broker-b-s.properties >/dev/null 2>&1 &

    查看启动日志:

    tail -f /root/rocketmq-s/logs/rocketmqlogs/broker.log

    2019-12-01 18:39:14 INFO brokerOutApi_thread_1 - register broker[1]to name server rocketmq1:9876 OK
    2019-12-01 18:39:17 WARN brokerOutApi_thread_2 - registerBroker Exception, rocketmq2:9876
    

    检查,可以了,这个机器部署完毕,我们将脚本写好,方便之后关闭虚拟机重启

    在root下创建startRocketmq.sh,内容如下:

    #!/bin/bash
    nohup sh /root/rocketmqbuild/namesrv/bin/mqnamesrv &
    nohup sh /root/rocketmqbuild/rocketmq-m/bin/mqbroker -c /root/rocketmqbuild/rocketmq-m/conf/2m-2s-sync/broker-a.properties >/dev/null 2>&1 &
    nohup sh /root/rocketmqbuild/rocketmq-s/bin/mqbroker -c /root/rocketmqbuild/rocketmq-s/conf/2m-2s-sync/broker-b-s.properties >/dev/null 2>&1 &
    

    B机器

    现在进行第二个虚拟机的配置,克隆下(非虚拟机,复制项目源码即可),修改ip地址,修改启动脚本,将配置文件修改

    #!/bin/bash
    nohup sh /root/rocketmqbuild/namesrv/bin/mqnamesrv &
    nohup sh /root/rocketmqbuild/rocketmq-m/bin/mqbroker -c /root/rocketmqbuild/rocketmq-m/conf/2m-2s-sync/broker-b.properties >/dev/null 2>&1 &
    nohup sh /root/rocketmqbuild/rocketmq-s/bin/mqbroker -c /root/rocketmqbuild/rocketmq-s/conf/2m-2s-sync/broker-a-s.properties >/dev/null 2>&1 &
    

    监控console

    为了方便我们观察生产者和消费者以及集群的状态,我们部署下console,为了方便部署,这里使用docker方式进行

    docker run -d -e "JAVA_OPTS=-Drocketmq.namesrv.addr=rocketmq1:9876;rocketmq2:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" --net=host -t styletang/rocketmq-console-ng
    

    这里需要注意的是使用了--net=host模式,再将对应虚拟机的8080端口打开即可,如果以端口映射方式需要考虑下网络问题(笔者比较笨,不搞了,怎么省事怎么来),按照如下操作:

    • 查看防火墙状态:firewall-cmd --state;若是未启动(not running),先启动,若已启动,直接下一步,启动命令:systemctl start firewalld.service;
    • 开启8080端口:firewall-cmd --zone=public --add-port=8080/tcp --permanent;
    • 重启防火墙:systemctl restart firewalld.service;
    • 重新加载配置:firewall-cmd --reload;

    浏览器打开console地址:http://192.168.211.11:8080,可观察到我们部署的集群信息


    集群信息

    测试

    这里使用源码中org.apache.rocketmq.example.quickstart目录下的Consumer和Producer进行测试

    生产者

            DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name");
            producer.setNamesrvAddr("192.168.211.11:9876;192.168.211.12:9876");
            producer.start();
            for (int i = 0; i < 1000; i++) {
                try {
                    Message msg = new Message("TopicTest" /* Topic */,
                        "TagA" /* Tag */,
                        ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
                    );
                    SendResult sendResult = producer.send(msg);
    
                    System.out.printf("%s%n", sendResult);
                } catch (Exception e) {
                    e.printStackTrace();
                    Thread.sleep(1000);
                }
            }
            producer.shutdown();
    

    生产成功

    这个生产消息的地方可能有些人看出来了有些问题,只发送到了其中一个broker上,这个跟我们配置参数autoCreateTopicEnable=true有关,之后的文章会通过源码进行分析说明,多了2条是之前测试的两条,大家可以忽略掉


    生产显示

    消费者

            DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_4");
            consumer.setNamesrvAddr("192.168.211.11:9876;192.168.211.12:9876");
            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
            consumer.subscribe("TopicTest", "*");
            consumer.registerMessageListener(new MessageListenerConcurrently() {
    
                @Override
                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                    ConsumeConcurrentlyContext context) {
                    System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
            });
            consumer.start();
            System.out.printf("Consumer Started.%n");
    

    消费成功

    消费显示

    另外可查看下消费配置:


    消费配置

    问题

    整个搭建流程是没什么疑问的,官方操作文档也比较好理解,但是在集群搭建中还是出现了一些问题,这里进行下记录:

    1.基础环境一定要先配置好,避免中途出现各种各样的问题

    2.配置文件从我的win10上复制到虚拟机中出现了一个像是字符集的问题,配置文件不起作用,启动脚本中-c这个地方我在centos7下一个一个的敲进去才起作用,我复制过去broker启动了但是配置参数看日志全是默认,找了半天,最后才找到是命令这里的问题,同样的store文件目录设置里也有个横杠,创建时候文件目录乱码了,才感觉应该是复制过去字符集不对了,后来将文件都修改了一遍才正常,比较尴尬,这个地方也没深究,之后有时间我再查查

    3.console用docker启动一定要注意网络的问题,有可能连上了namesrv,但是连接不上broker,观察下日志,我这里为了省事直接host网络模式

    4.autoCreateTopicEnable和autoCreateSubscriptionGroup参数(自动创建topic和自动创建订阅组)最好设置成false,在后台专门开发页面进行管理配置,先配置再使用

    总结

    本文主要说明了rocketmq的分布式集群搭建流程,笔者自己动手也是搞了半天才完成,大部分时间都耗费在找问题上了,也算是有些收获吧。当然,硬件限制,最多做到这种程度,搭建分布式集群也是为了后面阅读源码调试进行的准备,单个broker环境毕竟还是有点限制,大家按照流程操作即可,涉及到网络的部分尽量简化,后面自我感觉也要加强下网络基础的学习

    测试环境物理机如果是2台可以参考上述部署流程,jvm的参数调整下,线上环境还是至少4台物理机部署比较好,整体来说还算比较简单,比较好理解,希望对各位读者有所帮助

    以上内容如有问题欢迎指出,笔者验证后将及时修正,谢谢

    作者:freeorange
    个人博客网站:https://www.gclearning.cn/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    LeetCode——003 Longest Substring Without Repeating Characters
    LeetCode——002 Add Two Numbers
    LeetCode——001 Two Sum
    【日常训练】Hockey(CodeForces-96C)
    【日常训练】数据中心(CSP 201812-4)
    【赛后补题】Lucky Probability(CodeForces 110D)
    「Leetcode」14. Longest Common Prefix(Java)
    「Leetcode」13. Roman to Integer(Java)
    「日常训练」Magic Stones(CodeForces-1110E)
    「日常训练」Jongmah(Codeforces-1110D)
  • 原文地址:https://www.cnblogs.com/freeorange/p/12001320.html
Copyright © 2020-2023  润新知