精华内容
下载资源
问答
  • RabbitMQ集群

    2020-06-27 15:35:54
    RabbitMQ在设计之初,就内置了一个內建集群,该集群...这里我们就需要了解RabbitMQ集群在设计的时候的一些细节了,首先在RabbitMQ集群中,所有交换器会在整个集群上复制。这里我们主要来看一下RabbitMQ集群的队列,其队

    RabbitMQ在设计之初,就内置了一个內建集群,该集群可以允许消费者和生产者在节点崩溃的情况下继续运行;并且还可以通过添加节点线性扩展消息通信的吞吐量。


    但是其不能可以保证消息的可靠性,即当一个节点崩溃时,该节点上队列的消息也会消失,RabbitMQ默认不会将队列的消息复制到整个集群上。


    交换器和队列

    为什么会存在上述的问题呢?这里我们就需要了解RabbitMQ集群在设计的时候的一些细节了,首先在RabbitMQ集群中,所有交换器会在整个集群上复制。这里我们主要来看一下RabbitMQ集群的队列,其队列是不会在整个集群上进行完整复制的(只会复制队列的元数据——队列名称和属性(是否可持久化,是否自动删除等等))。


    集群中队列信息只会在队列的所有者节点保存队列的所有信息,其他节点只知道队列的元数据和指向所有者节点的指针,所以当节点崩溃时,该节点的队列和其上的绑定信息都消失了。


    那么为什么集群不复制队列内容和状态到所有节点呢(当然这也是可以通过镜像队列进行设置的)?这是出于以下几点进行考虑的:

    1. 存储空间,如果每个队列中存在非常多的消息,那么进行每个队列都需要在集群上进行复制,势必会占用很多的内存空间
    2. 性能,如果消息需要复制到集群中每个节点,网络开销不可避免,如果需要持久化消息还需要写磁盘。所以其他节点接收到不属于该节点的队列的消息时会将该消息传递给该队列的所有者节点上
    3. 另外当我们开启了消息的发送发确认模式,如果消息需要复制到集群中每个节点,那么就必须等到该消息复制到集群上的所有节点后,才会进行确认应答。

    集群中的节点

    在RabbitMQ集群中,所有的节点要么是内存节点,要么是磁盘节点。怎么区分?就是节点将队列、交换器、用户等等信息保存在哪里?单节点肯定是磁盘类型。集群中可以有内存节点,为了性能的考虑,全部是磁盘节点,当声明队列、交换器等等时,RabbitMQ必须将数据保存在所有节点后才能表示操作完成。


    Rabbitmq只要求集群中至少有一个磁盘节点,从高可用的角度讲每个集群应该至少配备两个磁盘节点。因为只有一个磁盘节点的情况下,当这个磁盘节点崩溃时,集群可以保持运行,但任何修改操作,比如创建队列、交换器、添加和删除集群节点都无法进行。




    接下来我们就来看一看如何构建一个RabbitMQ集群,需要注意的是,RabbitMQ集群对延迟非常敏感,只能在局域网内使用。


    在构建RabbitMQ集群时,首先我们需要将所有的机器中的 /etc/hosts 文件,将所有需要构建集群的机器添加进去,这里我们使用了192.168.80.135192.168.80.131两台虚拟机来构建RabbitMQ集群
    在这里插入图片描述
    在这里插入图片描述



    然后我们还需要修改Erlang的Cookie文件.erlang.cookie,我们需要将所有机器上该文件的内容修改为相同的,这里我们就将192.168.80.135 node1 机器上的内容复制到其他机器上进行修改。


    提示:.erlang.cookie文件路径,官方介绍集群的文档介绍如下: .erlang.cookie一般会存在于两个地方,第一个是:$HOME/.erlang.cookie ;第二个是:/var/lib/rabbitmq/.erlang.cookie 。


    即:如果我们使用rpm包方式或者yum安装,那么这个文件会存在于/var/lib/rabbitmq目录下。如果我们使用解压缩安装方式(二进制安装或者编译安装),那么该文件存在位置为$HOME目录下。即$HOME/.erlang.cookie 。如果我们使用root安装,则位置为:/root/.erlang.cookie ,其他用户为 /home/用户名/.erlang.cookie
    在这里插入图片描述
    在这里插入图片描述

    修改文件需要注意的是,我们从上述也可以看到该.erlang.cookie文件的权限是400,这里我们在修改其内容时,可以利用之前介绍的Linux常用命令来修改其文件权限,比如将其修改为777,然后再修改其文件内容,修改完后别忘记了将其文件权限再修改为原来的400,不然集群部署会出现一些奇怪的问题(当然我们也可以根据系统提示,直接加 ! 来强制修改文件内容)
    在这里插入图片描述



    然后我们需要将每一个机器的 /etc/hostname 中修改为 /etc/hosts 中的名称一致,最好重启虚拟机reboot,重启机器后,我们就会发现其hostname就被成功修改了,不再是原来的localhost,如下:
    在这里插入图片描述
    在这里插入图片描述



    然后我们就可以使用 rabbitmq-server -detached 来启动所有机器上的RabbitMQ应用,启动完成后,这里还没有完成,这里我们就要把其他的机器全部添加了其中的一台机器上面,这样才可以构建RabbitMQ集群,这里们就两台机器,所以我们把node2添加到node1上即可,


    那么该如何添加呢,首先我们需要关闭node2机器上的RabbitMQ应用,但是不能使用rabbitmqctl stop,应为该命令不仅会关闭RabbitMQ运行,还会将其Erlang也一同关闭,这里需执行 rabbitmqctl stop_app,仅关闭RabbitMQ应用
    在这里插入图片描述


    然后再需要执行 rabbitmqctl reset 来重置下机器上RabbitMQ的状态,如下:
    在这里插入图片描述


    然后就可以将该机器加入node1中,构建成RabbitMQ集群,执行rabbitmqctl join_cluster rabbit@node1
    在这里插入图片描述


    最后我们再通过 rabbitmqctl start_app 将node2上的RabbiteMQ应用启动即可
    在这里插入图片描述


    上述步骤就成功构建了RabbitMQ的集群,我们可以通过 rabbitmqctl cluster_status 命令来查看其检查集群状态(node1和node2均可)
    在这里插入图片描述

    上述我们可以看到RabbitMQ集群中共有两台机器,其中disc表示磁盘节点,下面还有一个running_nodes表示正常运行的节点,我们可以将node2节点关闭,然后再查看,肯定就一个正在运行的节点了。




    上述提到了disc磁盘节点,我们上述处理介绍磁盘节点,还有提到了内存节点,那么我们如何向RabbitMQ集群中,添加一个内存节点呢,这里我们就 node2 节点移除,然后作为内容节点添加到RabbitMQ集群中。


    这里我们要从RabbitMQ集群中移除,首先我们先执行 rabbitmqctl stop_app 来关闭RabbitMQ的应用,然后需要执行 rabbitmqctl reset 重置其状态
    在这里插入图片描述


    然后我们在将 node2 作为内存节点,使用 rabbitmqctl join_cluster rabbit@node1 --ram 添加至RabbitMQ集群中,然后再启动 node2 上的RabbitMQ应用即可
    在这里插入图片描述


    然后我们就可以使用 rabbitmqctl cluster_status 命令来查看其检查集群状态(node1和node2均可)
    在这里插入图片描述

    上述我们就可以看到 node2 被作为内存节点ram,成功添加到RabbitMQ集群中了。


    当然我们也是可以通过web管理页面来进行查看的,如下:
    在这里插入图片描述




    最后上述RabbitMQ集群构建完成后,我们在代码中进行测试下,首先我们创建一个生产者,其主要向 node1 节点上发布消息,如下:

    public class Producer {
    
        //交换器名称
        public static final String EXCHANGE_NAME = "logs";
    
        public static void main(String[] args) throws Exception {
            //创建连接,连接到RabbitMQ
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("192.168.80.135");
            connectionFactory.setUsername("root");
            connectionFactory.setPassword("root");
            Connection connection = connectionFactory.newConnection();
    
            //创建信道
            Channel channel = connection.createChannel();
    
            //创建主交换器
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT, false, false, null);
    
            //定义的业务日志消息级别,即作为路由键使用
            String[] logLevels = {"error", "warn", "info"};
            for (String logLevel : logLevels) {
                String msg = "Hello " + logLevel;
                //发布消息,需要参数:交换器、路由键,其中以日志消息级别为路由键
                channel.basicPublish(EXCHANGE_NAME, "", null, msg.getBytes(Charset.forName("UTF-8")));
            }
            channel.close();
            connection.close();
        }
    }
    

    然后我们再来创建两个消费者,一个消费者 node1 节点上的消息,一个消费者 node2 节点上的消息,如下:

    public class Consumer1 {
    
        public static final String EXCHANGE_NAME = "logs";
    
        public static void main(String[] args) throws Exception {
            //创建连接,连接到RabbitMQ,与发送端一样
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("192.168.80.135");
            connectionFactory.setUsername("root");
            connectionFactory.setPassword("root");
            Connection connection = connectionFactory.newConnection();
    
            //创建信道
            Channel channel = connection.createChannel();
            //可不创建,有生产者进行创建
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT, false, false, null);
    
            String queueName = "queue";  //声明一个队列名称
    
            //创建一个队列
            channel.queueDeclare(queueName, false, false, false, null);
    
            //将队列和交换器通过路由键进行绑定
            channel.queueBind(queueName, EXCHANGE_NAME, "#");
    
            //声明了一个消费者
            Consumer consumer = new DefaultConsumer(channel) {
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope,
                                           AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String message = "Exchange: " + envelope.getExchange() + ", " +
                            "RoutingKey: " + envelope.getRoutingKey() + ", " +
                            "MessageId: " + properties.getMessageId() + ", " +
                            "Content: " + new String(body, "UTF-8");
                    System.out.println(message);
                }
            };
    
            //消费者正式开始在指定队列上消费消息
            channel.basicConsume(queueName, true, consumer);
        }
    }
    
    public class Consumer2 {
    
        public static final String EXCHANGE_NAME = "logs";
    
        public static void main(String[] args) throws Exception {
            //创建连接,连接到RabbitMQ,与发送端一样
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("192.168.80.131");
            connectionFactory.setUsername("root");
            connectionFactory.setPassword("root");
            Connection connection = connectionFactory.newConnection();
    
            //创建信道
            Channel channel = connection.createChannel();
            //可不创建,有生产者进行创建
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT, false, false, null);
    
            String queueName = "queue";  //声明一个队列名称
    
            //创建一个队列
            channel.queueDeclare(queueName, false, false, false, null);
    
            //将队列和交换器通过路由键进行绑定
            channel.queueBind(queueName, EXCHANGE_NAME, "#");
    
            //声明了一个消费者
            Consumer consumer = new DefaultConsumer(channel) {
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope,
                                           AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String message = "Exchange: " + envelope.getExchange() + ", " +
                            "RoutingKey: " + envelope.getRoutingKey() + ", " +
                            "MessageId: " + properties.getMessageId() + ", " +
                            "Content: " + new String(body, "UTF-8");
                    System.out.println(message);
                }
            };
    
            //消费者正式开始在指定队列上消费消息
            channel.basicConsume(queueName, true, consumer);
        }
    }
    

    运行上述代码,测试结果如下:
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • RabbitMQ 集群

    2019-01-08 16:20:00
    RabbitMQ集群高可用- 1.1 单一模式- 1.2 普通模式- 1.3 镜像模式- 2. 集群的基本概念- 3. RabbitMQ普通模式集群配置- 3.1 安装 rabbitmq- 4. RabbitMQ 镜像集群配置- 5. 安装配置 Haproxy 1. RabbitMQ集群高可用...

    目录

    (见右侧目录栏导航)
    - 1. RabbitMQ集群高可用
        - 1.1 单一模式
        - 1.2 普通模式
        - 1.3 镜像模式
    - 2. 集群的基本概念
    - 3. RabbitMQ普通模式集群配置
        - 3.1 安装 rabbitmq
    - 4. RabbitMQ 镜像集群配置
    - 5. 安装配置 Haproxy

     

    1. RabbitMQ集群高可用


    RabbitMQ是用erlang开发的,集群非常方便,因为erlang天生就是一门分布式语言,但其本身并不支持负载均衡。
    Rabbit模式大概分为以下三种:
            (1) 单一模式
            (2) 普通模式
            (3) 镜像模式

     

    1.1 单一模式

        最简单的情况,非集群模式。

     

    1.2 普通模式


        默认的集群模式
        
        
        上面图中采用三个节点组成了一个RabbitMQ的集群,Exchange A (交换机)的元数据信息在所有节点上是一致的,而 Queue(存放消息的队列)的完整数据则只会存在于它所创建的那个节点上。其他节点只知道这个queue的metadata信息和一个指向queue的owner node的指针。
        
        (1)RabbitMQ集群元数据的同步
        
    RabbitMQ集群会始终同步四种类型的内部元数据(类似索引):
        a. 队列元数据:队列名称和它的属性;
        b. 交换机元数据:交换机名称、类型和属性;
        c. 绑定元数据:一张简单的表格展示了如何将消息路由到队列;
        d. vhost元数据:为vhost内的队列、交换机和绑定提供命名空间和安全属性;
            
        因此,当用户访问其中任何一个RabbitMQ节点时,通过Rabbitctl查询到的queue/user/exchange/vhost等信息都是相同的。
        
        对于Queue来说,消息实体只存在于其中一个节点,node1、node2、node3 三个节点仅有相同的元数据,即队列结构。
        当消息进入node1节点的Queue中后,consumer从node2节点拉取时,RabbitMQ会临时在node1、node2之间进行消息传输,把node1中的消息实体取出并经过node2发送给consumer。
        
        

    所以consumer应尽量连接每个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连A或B,出口总在A,会产生瓶颈。
    该模式存在一个问题就是当node1节点故障后,node2、node3节点无法取到node1节点中还未消费的消息实体。
    如果做了消息持久化,那么得等A节点恢复,然后才可被消费;如果没有持久化的话,那么数据就丢失了。    

    1.3 镜像模式

    把需要的队列做成镜像队列,存在于多个节点,属于RabbitMQ的HA方案。
    该模式解决了上述问题,其实和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在consumer取数据时临时拉取。
    该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。
    所以在对可靠性要求较高的场合中适用   

    2. 集群的基本概念

    RabbitMQ的集群节点包括内存节点、磁盘节点。顾名思义内存节点就是将所有数据放在内存,磁盘节点将数据放在磁盘。不过,如前文所述,如果在投递消息时,打开了消息的持久化,那么即使是内存节点,数据还是安全的放在磁盘。

    一个rabbitmq集 群中可以共享 user,vhost,queue,exchange等,所有的数据和状态都是必须在所有节点上复制的,rabbitmq节点可以动态的加入到集群中,一个节点它可以加入到集群中,也可以从集群环集群会进行一个基本的负载均衡。
    集群中有两种节点:
            (1) 内存节点:只保存状态到内存(一个例外的情况是:持久的queue的持久内容将被保存到disk)
            (2) 磁盘节点:保存状态到内存和磁盘。
    内存节点虽然不写入磁盘,但是它执行比磁盘节点要好。集群中,只需要一个磁盘节点来保存状态 就足够了
    如果集群中只有内存节点,那么不能停止它们,否则所有的状态,消息等都会丢失。

    集群实现思路:
    那么具体如何实现RabbitMQ高可用,我们先搭建一个普通集群模式,在这个模式基础上再配置镜像模式实现高可用,Rabbit集群前增加一个反向代理,生产者、消费者通过反向代理访问RabbitMQ集群,如图:
        

     

    3. RabbitMQ普通模式集群配置

     

      

     

    3.1 安装 rabbitmq

        (1)修改主机名、安装 rabbitmq
        
        192.168.118.15 、192.168.118.16、192.168.118.17 对应执行以下操作(主机各自的主机名)

    [root@192.168.118.15 ~]# hostnamectl set-hostname node1
    [root@192.168.118.15 ~]# hostname node1
    [root@192.168.118.15 ~]# cd /opt/
    [root@192.168.118.15 /opt]# ls??
    # erlang、rabbitmq-server 下载地址:http://ww.rabbitmq.com/releases/
    erlang-19.0.4-1.el6.x86_64.rpm??rabbitmq-server-3.6.13-1.el7.noarch.rpm
    [root@192.168.118.15 /opt]# yum install *.rpm -y

     


    只需在node1(192.168.118.15)上启动服务

    [root@192.168.118.15 /opt]#systemctl start rabbitmq-server  # 启动服务
    [root@192.168.118.15 ~]#rabbitmq-plugins enable rabbitmq_management # 开启后端web管理
    [root@192.168.118.15 ~]#netstat -ntplu | egrep beam
    tcp        0      0 0.0.0.0:25672           0.0.0.0:*               LISTEN      4557/beam           
    tcp        0      0 0.0.0.0:15672           0.0.0.0:*               LISTEN      4557/beam           
    tcp6       0      0 :::5672                 :::*                    LISTEN      4557/beam

     


        
        (2)拷贝 .erlang.cookie
        
        Rabbitmq的集群是依附于erlang的集群工作的,所以必须先构建起erlang的集群模式。erlang.cookie是erlang实现分布式的必要文件,erlang分布式的每个节点上要保持相同的.erlang.cookie文件,同时保证文件的权限是400

    [root@192.168.118.15 ~]#cat /var/lib/rabbitmq/.erlang.cookie 
    GFCOJDLAKUIEJCLKCNVR

     


        
        将 192.168.118.15 的 .erlang.cookie 文件拷贝到 192.168.118.16、192.168.118.17 对应的目录下并设置权限

    [root@192.168.118.15 ~]#scp /var/lib/rabbitmq/.erlang.cookie node2:/var/lib/rabbitmq/
    [root@192.168.118.15 ~]#scp /var/lib/rabbitmq/.erlang.cookie node3:/var/lib/rabbitmq/
    分别在 192.168.118.16192.168.118.17 赋予权限
    
    192.168.118.16
    [root@192.168.118.16 ~]#ll /var/lib/rabbitmq/.erlang.cookie 
    -r-------- 1 root root 20 Jan  7 20:43 /var/lib/rabbitmq/.erlang.cookie
    [root@192.168.118.16 ~]#chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie
    192.168.118.17
    [root@192.168.118.17 ~]#ll /var/lib/rabbitmq/.erlang.cookie
    -r-------- 1 root root 20 Jan  7 20:45 /var/lib/rabbitmq/.erlang.cookie
    [root@192.168.118.17 ~]#chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie
    
    开启 node2(192.168.118.16) node3(192.168.118.17) 服务
    
    [root@192.168.118.16 ~]#systemctl start rabbitmq-server
    [root@192.168.118.17 ~]#systemctl start rabbitmq-server

     


        
        (3)将node2(192.168.118.16)、node3(192.168.118.17) 作为内存节点加入node1(192.168.118.15)节点集群中

    node2(192.168.118.16)
    [root@192.168.118.16 ~]#rabbitmqctl stop_app 
    Stopping rabbit application on node rabbit@node2
    [root@192.168.118.16 ~]#rabbitmqctl join_cluster --ram rabbit@node1
    Clustering node rabbit@node2 with rabbit@node1
    [root@192.168.118.16 ~]#rabbitmqctl start_app
    Starting node rabbit@node2
    
    node3(192.168.118.17)
    [root@192.168.118.17 ~]#rabbitmqctl stop_app    # 停止rabbit应用
    Stopping rabbit application on node rabbit@node3
    [root@192.168.118.17 ~]#rabbitmqctl join_cluster --ram rabbit@node1     # 加入到磁盘节点
    Clustering node rabbit@node3 with rabbit@node1
    [root@192.168.118.17 ~]#rabbitmqctl start_app   # 启动rabbit应用
    Starting node rabbit@node3

     


            A. 默认rabbitmq启动后是磁盘节点,在这个cluster命令下,node2和node3是内存节点,node1是磁盘节点。
            B. 如果要使node2、node3都是磁盘节点,去掉--ram参数即可。
            C. 如果想要更改节点类型,可以使用命令rabbitmqctl change_cluster_node_type disc(ram),前提是必须停掉rabbit应用。


        (4)查看集群状态

    [root@192.168.118.15 ~]#rabbitmqctl cluster_status 
    Cluster status of node rabbit@node1
    [{nodes,[{disc,[rabbit@node1]},{ram,[rabbit@node3,rabbit@node2]}]},
    {running_nodes,[rabbit@node3,rabbit@node2,rabbit@node1]},  # 正在运行中的集群节点
    {cluster_name,<<"rabbit@node1">>},
    {partitions,[]},
    {alarms,[{rabbit@node3,[]},{rabbit@node2,[]},{rabbit@node1,[]}]}]

     


        (5)为rabbit添加用户并授权

    [root@192.168.118.15 ~]#rabbitmqctl add_user admin admin    # 新建用户
    Creating user "admin"
    [root@192.168.118.15 ~]#rabbitmqctl set_user_tags admin administrator   # 赋予管理员角色
    Setting tags for user "admin" to [administrator]
    [root@192.168.118.15 ~]#rabbitmqctl set_permissions admin '.*' '.*' '.*'    # 授予管理、写、读权限
    Setting permissions for user "admin" in vhost "/"

     


        
        (6)登录rabbitmq web管理控制台,创建新的队列
        
        打开浏览器输入 http://192.168.118.15:15672/ 刚才的创建的用户:admin 密码: admin,登录后出现如图:
        
            
        根据页面提示创建一条队列

     

    在RabbitMQ普通集群中,必须至少有一个磁盘节点,否则队列元数据无法写入到集群中,当磁盘节点宕掉时,集群将无法写入新的队列元数据信息。
        
    到此,rabbitmq 普通模式搭建完毕。
        

    4. RabbitMQ 镜像集群配置


        上面已经完成RabbitMQ默认集群模式,但并不保证队列的高可用性,尽管交换机、绑定这些可以复制到集群里的任何一个节点,但是队列内容不会复制。虽然该模式解决一项目组节点压力,但队列节点宕机直接导致该队列无法应用,只能等待重启,所以要想在队列节点宕机或故障也能正常应用,就要复制队列内容到集群里的每个节点,必须要创建镜像队列。
        镜像队列是基于普通的集群模式的,然后再添加一些策略,所以你还是得先配置普通集群,然后才能设置镜像队列,我们就以上面的集群接着做。
        
        设置的镜像队列可以通过开启的网页的管理端,也可以通过命令,这里说的是其中的网页设置方式。
        
        (1) 创建rabbitmq策略
        在node1(192.168.118.15)节点的控制台上创建策略
                A. 点击admin菜单–>右侧的Policies选项–>左侧最下下边的Add/update a policy。
                B. 按照图中的内容根据自己的需求填写。

     

            Name:策略名称
            Pattern:匹配的规则,这里表示所有的队列,如果是匹配以a开头的队列,那就是^a.
            Definition:使用ha-mode模式中的all,也就是同步所有匹配的队列。问号链接帮助文档。

     


            点击Add policy添加策略

     

        此时分别登陆node2、node3两个节点的控制台,可以看到上面添加的这个策略,如图所示:
        
        node2


        node3


        (2)添加队列
            在node1节点的控制台上添加队列
                    A. 点击Queues菜单–>左侧下边的Add a new queue
                    B. 输入Name和Arguments参数的值,别的值默认即可

     

    Name:队列名称
    Durability:队列是否持久化
    Node:消息队列的节点
    Auto delete:自动删除
    Arguments:使用的策略类型

     


            将鼠标指向+2可以显示出另外两台消息节点。
        

     

        (3)创建消息
                A. 点击superman队列按钮
                B. 拖动滚动条,点击publish message
                C. 填写相关内容

     

            2-Persistent:表示持久化

    Headers:随便填写即可
    Properties:点击问号,选择一个消息ID号
    Payload:消息内容

     


            点击queue按钮,发现superman队列的Ready和Total中多了一条消息记录。


        (4)做破坏性测试
            A. 将node1节点的服务关闭,再通过node2和node3查看消息记录是否还存在。
                停止 node1 rabbitmq服务

    [root@192.168.118.15 ~]#systemctl stop rabbitmq-server

     

            node2

            node3

            从中可以看到ab队列已经从之前的+2显示成+1了,而且消息记录是存在的。
            B. 再将node2(192.168.118.16)节点的服务关闭,通过node3查看消息记录是否还存在。

    [root@192.168.118.16 ~]#systemctl stop rabbitmq-server

     

     

            从中可以看到superman队列和消息记录还是存在的,只是变成了一个节点了。
        
            C. 将node1和node2的服务再启动起来

    [root@192.168.118.15 ~]#rabbitmqctl sync_queue superman
    [root@192.168.118.16 ~]#rabbitmqctl sync_queue superman


            从提示中显示镜像无法同步。如果这时候停掉node3节点的服务,那么队列里面的消息将会丢失。
            启动后,不同步的解决方法是在node1、node2节点上执行同步命令。

    [root@192.168.118.15 ~]#rabbitmqctl sync_queue superman
    [root@192.168.118.16 ~]#rabbitmqctl sync_queue superman

                同步完成后,就显示同步镜像的节点。
                这样,我们就测试了rabbitmq集群的破坏性测试,说明集群配置成功。

     

    5. 安装配置 Haproxy

     

        (1)修改主机名

    [root@192.168.118.14 ~]#hostnamectl set-hostname haproxy ; hostname haproxy

     


        (2)安装haproxy  这里就直接使用epel源安装haproxy

    [root@192.168.118.14 ~]#yum install haproxy -y

     


        (3)修改配置文件

        [root@192.168.118.14 ~]#egrep -v '#|^$' /etc/haproxy/haproxy.cfg 
        global
            log         127.0.0.1 local2
            chroot      /var/lib/haproxy
            pidfile     /var/run/haproxy.pid
            maxconn     4000
            user        haproxy
            group       haproxy
            daemon
            stats socket /var/lib/haproxy/stats
        defaults
            mode                    http
            log                     global
            option                  httplog
            option                  dontlognull
            option http-server-close
            option forwardfor       except 127.0.0.0/8
            option                  redispatch
            retries                 3
            timeout http-request    10s
            timeout queue           1m
            timeout connect         10s
            timeout client          1m
            timeout server          1m
            timeout http-keep-alive 10s
            timeout check           10s
            maxconn                 3000
            
            
        listen http_front   # haproxy 管理后台
            bind 0.0.0.0:1080   # 监听端口
            mode http           # 开启模式为http
            stats enable        # 开启后台统计
            stats hide-version  # 隐藏统计页面上HAProxy的版本信息
            stats refresh 30s   # 统计页面自动刷新时间
            stats uri /stats    # 统计页面uri
            stats realm Haproxy Manager # 统计页面密码框上提示文本 
            stats auth admin:admin  # 统计页面用户名和密码设置
            stats admin if TRUE # 此项是实现haproxy监控页的管理功能的
            
            
        listen rabbitmq_cluster # RabbitMQ 集群负载
            bind 0.0.0.0:5672   # 监听端口
            option tcplog
            mode tcp
            timeout client 3h
            timeout server 3h
            option clitcpka
            balance roundrobin  # 负载均衡算法
            server node2 192.168.118.16:5672 check inter 5s rise 2 fall 3
            server node3 192.168.118.17:5672 check inter 5s rise 2 fall 3

     

        server <name>:定义haproxy内RabbiMQ服务的标识
        ip:port: 标识了后端RabbitMQ的服务地址
        check inter 5s: 表示每个5秒检测RabbitMQ服务是否可用
        rise 2: 表示RabbitMQ服务在发生故障之后,需要2次健康检查才能被再次确认可用
        fall 3: 表示需要经历 3 次失败的健康检查之后,HaProxy才会停止使用此RabbitMQ服务

     


        具体HaProxy 相关说明:https://www.cnblogs.com/hukey/p/5586765.html

        (4)启动haproxy

    [root@192.168.118.14 ~]#systemctl start haproxy
    [root@192.168.118.14 ~]#netstat -ntplu | egrep haproxy 
    tcp        0      0 0.0.0.0:5672            0.0.0.0:*               LISTEN      19006/haproxy       
    tcp        0      0 0.0.0.0:1080            0.0.0.0:*               LISTEN      19006/haproxy       
    udp        0      0 0.0.0.0:43437           0.0.0.0:*                           19005/haproxy

     
        通过浏览器登录haproxy统计后台 http://192.168.118.14:1080/stats
        


        到此,RabbitMQ + HaProxy 高可用集群搭建完毕,后面可自行进行测试。


        本文参考链接:
            
            http://blog.51cto.com/11134648/2155934
            https://www.jianshu.com/p/6376936845ff

    转载于:https://www.cnblogs.com/hukey/p/10239632.html

    展开全文
  • Rabbitmq 集群

    2021-02-26 11:16:33
    Rabbitmq 集群 集群目的就是为了实现rabbitmq的高可用性,集群分为2种 普通集群:主备架构,只是实现主备方案,不至于主节点宕机导致整个服务无法使用 镜像集群:同步结构,基于普通集群实现的队列同步 普通集群 ...

    Rabbitmq 集群

    集群目的就是为了实现rabbitmq的高可用性,集群分为2种

    • 普通集群:主备架构,只是实现主备方案,不至于主节点宕机导致整个服务无法使用
    • 镜像集群:同步结构,基于普通集群实现的队列同步

    普通集群

    slave节点复制master节点的所有数据和状态,除了队列数据,队列数据只存在master节点,但是Rabbitmq slave节点可以实现队列的转发,也就是说消息消费者可以连接到slave节点,但是slave需要连接到master节点转发队列,由此说明只能保证了服务可以用,无法达到高可用
    在这里插入图片描述

    slave节点队列可以查看到,但是不会同步数据

    镜像集群
    基于普通集群实现队列的集群主从,消息会在集群中同步(至少三个节点)
    在这里插入图片描述
    镜像集群部署

    环境准备
    在这里插入图片描述
    配置hosts

    cat >> /etc/hosts << EOL
    192.168.12.10 controller
    192.168.12.11 standby1
    192.168.12.12 standby2
    EOL
    

    配置.erlang.cookie

    RabbitMQ 的集群是依赖 erlang 集群,而 erlang 集群是通过这个 cookie 进行通信认证的,因此,三台机器的配置文件需要一致

    • 目录:/var/lib/rabbitmq/.erlang.cookie (隐藏文件)
    rabbitmq-server -detached	
    #启动rabbitmq服务才能查看到.erlang.cookie文件(三台都要启动)
    rabbitmqctl stop_app
    #停止掉2个standby节点,不然复制后操作会提示认证问题,因为erlang.cookie改变了,需要kill才行
    scp /var/lib/rabbitmq/.erlang.cookie root@standby1:/var/lib/rabbitmq/
    scp /var/lib/rabbitmq/.erlang.cookie root@standby2:/var/lib/rabbitmq/
    #替换erlang.cookie文件
    

    加入集群(节点操作加入)

    rabbitmqctl cluster_status
    #查看集群,默认集群就是自己
    rabbitmqctl stop_app 
    rabbitmqctl reset
    rabbitmqctl join_cluster rabbit@controller
    rabbitmqctl start_app
    #停止服务、重启之前的数据、加入集群
    

    报错解决
    在这里插入图片描述

    rabbitmqctl start_app
    #controller节点
    

    在这里插入图片描述

    rabbitmq-server -detached
    rabbitmqctl stop_app
    #再次启动后停止
    

    查看集群状态
    在这里插入图片描述
    开启web管理页面

    rabbitmq-plugins enable rabbitmq_management (三个节点)
    #url:http://192.168.12.10:15672/
    #默认账号:guest guest
    

    在这里插入图片描述
    实现队列的集群

    基于普通镜像通过配置策略的方式实现,policy可以选择exchanges 或者 queue 的数据需要复制同步,以及如何复制同步

    • 可以基于命令行配置
    • 支持web管理界面配置

    策略格式

    rabbitmqctl set_policy [-p ] [–priority <priorityz] [–apply-to <apply-to2]

    • -p Vhost: 可选参数,针对指定vhost下的queue进行设置
    • Name:priority 名称
    • Pattern: queue的匹配模式(使用正则表达式)
    • Definition:镜像定义,包括三个部分ha-mode, ha-params, ha-sync-mode
      • ha-mode:指明镜像队列的模式,有效值为all/exactly/nodes
        • all:表示在集群中所有的节点上进行镜像
        • exactly:表示在指定个数的节点上进行镜像,节点的个数由ha-params指定
        • nodes:表示在指定的节点上进行镜像,节点名称通过ha-params指定
      • ha-params: ha-mode模式需要用到的参数
      • ha-sync-mode:进行队列中消息的同步方式,有效值为automatic和manual
    • priority:可选参数, policy的优先级

    配置策略

    rabbitmqctl set_policy ha-all '^' '{"ha-mode":"all","ha-sync-mode":"automatic"}'
    #策略名 ha-all
    #匹配所有的队列,也可以具体单个,比如'^test' 
    #三个节点都进行队列镜像
    #自动同步
    

    查看策略

    rabbitmqctl list_policies
    

    在这里插入图片描述
    在这里插入图片描述测试关闭controller节点

    rabbitmqctl stop_app
    

    在这里插入图片描述
    在这里插入图片描述
    查看后发现节点已经变成standby2,数量也减少了一个

    恢复controller节点

    rabbitmqctl start_app
    

    在这里插入图片描述
    查看后,说明集群节点不会被抢回,其实这样也是合理的

    参考:https://www.rabbitmq.com/clustering.html
    参考视频:https://www.bilibili.com/video/BV1dE411K7MG?p=19

    卸载rabbitmq(干净)

    yum -y remove rabbitmq-server.noarch
    yum -y remove erlang-* 
    rm -rf /usr/lib64/erlang
    rm -rf /var/lib/rabbitmq
    
    展开全文
  • Rabbitmq集群

    2021-04-28 21:47:38
    Rabbitmq集群 1、停止所有节点rabbitmq 2、配置各节点中的hosts文件(编辑文件命令:vi /etc/hosts) 192.168.59.100 rabbitmq1 192.168.59.101 rabbitmq2 192.168.59.102 rabbitmq3 配置好一台服务器后,可以通过...

    Rabbitmq集群

    没安装RabbitMQ的同学请点击《Linux安装RabbitMQ,官方推荐方式》

    1、停止所有节点rabbitmq
    2、配置各节点中的hosts文件(编辑文件命令:vi /etc/hosts)

    192.168.59.100 rabbitmq1
    192.168.59.101 rabbitmq2
    192.168.59.102 rabbitmq3
    

    配置好一台服务器后,可以通过复制命令复制到其它服务器中(命令中root是用户名,rabbitmq2可以是指定复制到服务器的ip)

    scp /etc/hosts root@rabbitmq2:/etc/
    

    3、保证每台节点服务器的.erlang.cookie文件一致(可以通过下面的命令,从主节点中,把文件复制到其它节点服务器,从而保证.erlang.cookie文件一致)

    scp /var/lib/rabbitmq/.erlang.cookie root@rabbitmq2:/var/lib/rabbitmq/.erlang.cookie
    

    4、重启一下各个节点的服务器
    5、后台启动所有rabbitmq

    rabbitmq-server -detached
    查看rabbitmq后台运行状态
    rabbitmqctl cluster_status
    

    6、关闭子节点(主节点不要关闭)

    rabbitmqctl stop_app
    

    7、子节点服务器上加入集群(如果执行命令报错,有可能是你主服务器的防火墙没关,或者防火墙端口没放行)

    rabbitmqctl join_cluster rabbit@rabbitmq1
    

    8、启动子节点rabbitmq

    rabbitmqctl start_app
    

    9、镜像模式设置,登录管理界面
    在这里插入图片描述

    展开全文
  • rabbitmq 集群

    2020-12-02 15:54:11
    rabbitmq集群允许消费者和生产者在RabbitMQ单个节点崩溃的情况下继续运行,它可以通过添加更多的节点来线性的扩展消息通信的吞吐量。当失去一个rabbitMQ节点时,客户端能够重新连接到集群中的任何其他节点并继续生产...
  • rabbitMq集群

    2016-08-18 14:40:03
    rabbitMq3.6.5集群部署,已成功运行
  • rabbitMQ集群

    2021-04-26 09:04:56
    先停止rabbitMQ服务 service rabbitmq-server stop 开启第一个节点 RABBITMQ_NODE_PORT=5673 RABBITMQ_NODENAME=rabbit1 rabbitmq-server start 复制一个会话开启第二个节点 RABBITMQ_NODE_PORT=5674 RABBITMQ_...
  • RabbitMq集群

    2019-08-26 11:45:53
    介绍一下RabbitMq集群rabbitMq三种模式: 第一种单体结构 第二种普通模式 第三种镜像模式 第一种:在不这里不做介绍,搭建完成就是第一种。 第二种:默认模式 默认模式,例举一个例子两台服务器分...
  • rabbitmqctl join_cluster rabbit@rabbitmq_01

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,713
精华内容 2,685
关键字:

rabbitmq集群