• CentOS系统用docker搭建rabbitMQ集群


    文章目录


    前言

    因项目需要使用RabbitMQ来进行模块之前的消息传递,且之前未有相关的经验,所以特此记录下RabbitMQ集群的搭建及调试过程。另外简单的介绍下RabbitMQ的两种集群模式,即普通模式与镜像模式,这两种模式的区别就是在于普通模式仅会同步元数据,当消费消息时,如果连接到了另外一个实例,那么那个实例会通过元数据定位到队列所在位置,然后访问队列所在的实例,拉取数据过来发送给消费者;而集群模式会同步所有的副本数据,每次写入消息时都会自动把数据同步到多台实例上去。


    一、环境准备

    1. 两台云服务器(centos7.5-丐版-1核2G),若没有,可用虚拟机。
      两台服务器ip如下:
      机器1:1.117.251.181
      机器2:121.36.159.27
    2. 已有docker镜像,本人用的镜像为:rabbitmq:3.7.16-management
      在这里插入图片描述

    二、部署RabbitMQ

    1.在机器1上安装RabbitMQ

    执行命令

    docker run  -d --hostname rabbitmq1 --add-host=rabbitmq2:121.36.159.27 --restart=unless-stopped --name rabbitmq1 --net host -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -e RABBITMQ_ERLANG_COOKIE='rabbit_mq_2022' rabbitmq:3.7.16-management
    
    • 1

    部分参数解释

    --hostname rabbitmq1 容器的主机名为 rabbitmq1
    
    --add-host=rabbitmq2:121.36.159.27  修改容器内部的hosts
    
    --restart=unless-stopped docker 容器重启后重启MQ
    
    --name rabbitmq1 容器名为rabbitma1
    
    -e RABBITMQ_DEFAULT_USER=admin 设置rabbitmq默认用户为admin
    
    -e RABBITMQ_DEFAULT_PASS=admin 设置rabbitmq默认密码为admin
    
    -e RABBITMQ_ERLANG_COOKIE='rabbit_mq_2022' 设置rabbitmq的cookie为“rabbit_mq_2022”,可以自定义为其他文本,容器保持一致即可
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    docker ps -a ,查看容器状态

    在这里插入图片描述

    浏览器输入RabbitMQ管理地址

    在这里插入图片描述

    2.在机器2上安装RabbitMQ

    执行命令

    docker run  -d --hostname rabbitmq2 --add-host=rabbitmq1:1.117.251.181 --restart=unless-stopped --name rabbitmq2 --net host -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -e RABBITMQ_ERLANG_COOKIE='rabbit_mq_2022' rabbitmq:3.7.16-management
    
    • 1

    docker ps -a ,查看容器状态

    在这里插入图片描述

    浏览器输入RabbitMQ管理地址

    在这里插入图片描述

    tips: 对于有云服务器的朋友,这边的话需要在云服务器的控制台配置对应的防火墙(安全组)策略,需要将5672、15672、25672、4369配置进去。

    三、搭建普通集群模式

    1.rabbitmq1容器配置

    进入容器

    docker exec -it rabbitmq1 /bin/bash
    
    • 1

    进入容器后通过rabbitmqctl命令对MQ进行操作

    #首先停止当前MQ
    rabbitmqctl stop_app
    #resetMQ
    rabbitmqctl reset
    #重新启动MQ
    rabbitmqctl start_app
    退出容器
    exit
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.rabbitmq2容器配置

    进入容器

    docker exec -it rabbitmq2 /bin/bash
    
    • 1

    进入容器后通过rabbitmqctl命令对MQ进行操作

    #首先停止当前MQ
    rabbitmqctl stop_app
    #resetMQ
    rabbitmqctl reset
    #跟机器1的消息队列建立关系
    rabbitmqctl join_cluster --ram rabbit@rabbitmq1
    #重新启动MQ
    rabbitmqctl start_app
    退出容器
    exit
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这时rabbitmq1与rabbitmq2的集群关系搭建完成,可以去管理页面看下。
    在这里插入图片描述

    四、代码测试

    新建两个模块,rabbitmq-provider(消息生产者),rabbitmq-receiver(消息接收者)。

    1.rabbitmq-provider相关代码

    pom依赖

    
        org.springframework.boot
        spring-boot-starter-amqp
    
    
        org.springframework.boot
        spring-boot-starter-web
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    配置文件

    spring.rabbitmq.addresses=1.117.251.181:5672,121.36.159.27:5672
    spring.rabbitmq.username=admin
    spring.rabbitmq.password=admin
    
    • 1
    • 2
    • 3

    配置类

    package com.qcc.rabbitmqprovider.config;
    
    import org.springframework.amqp.core.*;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    
    /**
     * @创建人 qianchengcheng
     * @创建时间 2022/4/28
     * @描述 rabbitmq配置类
     */
    @Configuration
    public class RabbitmqConfig {
    
        public static final String QCC_QUEUE_NAME = "qcc_queue_name";
        public static final String QCC_EXCHANGE_NAME = "qcc_exchange_name";
    
        @Bean
        Queue queue() {
            return new Queue(QCC_QUEUE_NAME, true, false, false);
        }
    
        @Bean
        FanoutExchange directExchange() {
            return new FanoutExchange(QCC_EXCHANGE_NAME, true, false);
        }
    
        @Bean
        Binding binding() {
            return BindingBuilder.bind(queue())
                    .to(directExchange());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    测试类

    package com.qcc.rabbitmqprovider;
    
    import com.qcc.rabbitmqprovider.config.RabbitmqConfig;
    import org.junit.jupiter.api.Test;
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    class RabbitmqProviderApplicationTests {
    
        @Autowired
        private RabbitTemplate rabbitTemplate;
    
        @Test
        void contextLoads() {
            rabbitTemplate.convertAndSend(RabbitmqConfig.QCC_EXCHANGE_NAME,null,"hello~qcc");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    运行下测试类,消息发送成功后,可以在管理页面看到队列中的消息
    在这里插入图片描述
    在这里插入图片描述

    2.rabbitmq-receiver相关代码

    其他配置、代码均一样,新增一个消息接收类

    消息接收类

    package com.qcc.rabbitmq.receiver;
    
    import com.qcc.rabbitmq.config.RabbitmqConfig;
    import com.rabbitmq.client.Channel;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.amqp.core.Message;
    import org.springframework.amqp.rabbit.annotation.RabbitHandler;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    import java.io.IOException;
    
    /**
     * @创建人 qianchengcheng
     * @创建时间 2022/4/28
     * @描述 rabbitmq消费者
     */
    @Component
    public class RabbitReceiveMessage {
    
        private static Logger log = LoggerFactory.getLogger(RabbitReceiveMessage.class);
    
        @RabbitListener(queues = RabbitmqConfig.QCC_QUEUE_NAME)
        @RabbitHandler
        public void msg(Message message, Channel channel) throws IOException{
            try {
                byte[] body = message.getBody();
                log.info("接收的消息为:{}",new String(body,"utf-8"));
            }catch (Exception e){
                e.printStackTrace();
                log.info("处理mq消息异常");
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    运行消息接收服务,此时控制台会打印出一条接收到的数据
    在这里插入图片描述
    结合mq管理系统可以看出,队列中消息的数量都变成了0。
    tips: 我们可以看到,当提供者生产了一条消息时,此时从mq的系统中发现两个实例的队列中数量均为1,但是实际上消息本身只存在于一个 RabbitMQ 实例,为此,我们可以简单的做个测试。

    3.反向测试

    这里我们先停掉receiver服务,然后通过 provider 发送一条消息,发送成功之后,关闭rabbitmq1实例,此时再启动我们的receiver服务,会发现没有消息接收,这就说明了,消息并没有进行同步。

    五、尝试镜像模式

    1.新建Policies

    点击admin菜单–>右侧的Policies选项–>左侧最下下边的Add/update a policy。
    在这里插入图片描述
    可以参照我的新建一个,建完之后点击左下角的 apply policy。此时队列中已经添加了该策略,如下图所示:
    在这里插入图片描述
    此时,我们可以按照之前的反向测试方式,对该模式进行测试。

    2.反向测试

    这里我们先停掉receiver服务,然后通过 provider 发送一条消息,发送成功之后,关闭rabbitmq1实例,此时再启动我们的receiver服务,会发现有一条消息接收,这就说明了,消息已经进行了同步。

    发送了一条消息

    在这里插入图片描述

    关闭其中一个实例

    在这里插入图片描述

    启动receiver服务

    在这里插入图片描述


    总结

    通过简单的部署及测试,了解了rabbitmq普通集群和镜像集群的区别,普通模式在消息未持久化的场景下,可靠性不高,而镜像模式由于进行了消息的同步,所以可靠性高,但是由于消息的同步会有额外的性能消耗。具体使用哪个,需结合自身业务场景来定,最后,谢谢各位的观看~

  • 相关阅读:
    8.tomcat优化
    是时候使用 YAML 来做配置或数据文件了
    将vscode打造无敌的IDE(14) tasks.json和launch.json配置详解,随心所欲添加自动化任务
    Ubuntu 20.04 安装 mysql 8
    识别图片转文字怎么弄?推荐两种实用工具
    lv5 嵌入式开发-12 信号灯
    编译器优化:何为SLP矢量化
    High Performance Computing 综述
    欢迎 Gemma: Google 最新推出开源大语言模型
    idea导入springboot项目运行教程
  • 原文地址:https://blog.csdn.net/asdfadafd/article/details/126326896