RabbitMQ集群高可用原理及实战部署是怎样的

技术RabbitMQ集群高可用原理及实战部署是怎样的这篇文章将为大家详细讲解有关RabbitMQ集群高可用原理及实战部署是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了

本文将详细解释RabbitMQ集群的高可用性原理和实际部署。这篇文章的内容质量很高,所以边肖会分享给大家作为参考。希望你看完这篇文章后有所了解。

今天,我们来谈谈RabbitMQ集群原理和部署流程。

00-1010在之前的文章中,我们详细介绍了rabbtmq的内部结构和用途,以及SpringBoot和rabbtmq的集成,所有这些都是基于单一的rabbtmq。

我们知道,随着微服务的普及,一旦单个服务器挂机,基本上不可能提供高可用的服务。因此,为了确保服务的高可用性,我们在生产环境中通常的做法是构建一个RabbitMQ集群。即使有一台rabbtmq出现故障,其他正常的rabbtmq服务器仍然可以使用,不会影响应用的持续运行。

00-1010在前面的文章中,我们介绍了RabbitMQ中有各种基本组件,包括队列、交换机、绑定、虚拟主机等。它们构成了AMQP协议消息通信的基础,并且这些组件以元数据,的形式存在,该形式总是记录在RabbitMQ中。它们是:

队列元数据:队列名称及其属性交换器元数据:交换机名称、类型和属性绑定元数据:一个简单的表显示了如何为vhost中的队列将消息路由到队列vhost 元数据:交换机和绑定提供了元数据,如命名空间和安全属性。实际上,它本质上是一个查询表,包括交换机的名称和队列的绑定列表。当您向交换机发布消息时,您实际上是将消息上的路由密钥与通道中交换机的绑定列表进行匹配,然后将消息路由出去。

RabbitMQ集群高可用原理及实战部署是怎样的

有了消息路由表中的这个机制,在所有节点上传输交换机消息就会容易得多,而RabbitMQ所做的就是将交换机元数据复制到所有节点上,这样每个节点上的每个通道都可以访问完整的交换机。

RabbitMQ集群高可用原理及实战部署是怎样的

如果消息生产者连接到节点2或节点3,此时队列1的完整数据不在这两个节点上,那么这两个节点在发送消息的过程中主要起到路由和转发的作用。根据这两个节点上的元数据,消息将被转发到节点1,最终发送的消息仍将存储在节点1的队列1中。

类似地,如果消息使用者连接到节点2或节点3,这两个节点也将充当路由节点,并将从节点1的队列1中提取消息以供使用。

与常见的集群主从架构模式不同的地方在于:RabbitMQ 集群模式下,仅仅只是同步元数据,每个队列内容还是在自己的服务器节点上.

该设计主要基于集群本身的性能和存储空间:

存储空间:存储数据的真正地方在队列中。如果每个集群节点都有所有队列的完整数据副本,那么每个节点的存储空间会非常大,集群的消息积压能力也会非常弱。比如你现在存储3G队列的内容,那么在另一个只有1G存储空间的节点上,就会出现内存空间不足的情况,也就是不可能通过扩展集群节点来提高消息积压容量。性能:消息的发布者需要将消息复制到每个集群节点,每条消息都会触发磁盘活动,这将导致整个集群的性能负载急剧增加。由于每个队列的内容仍然在它自己的服务器节点上,这也会带来新的问题,那就是如果队列所在服务器挂了,那存在服务器上的队列数据是不是全部都丢失了?

在单个节点上,RabbitMQ有两种存储数据的方案:

" class=" list-paddingleft-2">

  • 内存模式:这种模式会将数据存储在内存当中,如果服务器突然宕机重启之后,那么附加在该节点上的队列和其关联的绑定都会丢失,并且消费者可以重新连接集群并重新创建队列;
  • 磁盘模式:这种模式会将数据存储磁盘当中,如果服务器突然宕机重启,数据会自动恢复,该队列又可以进行传输数据了,并且在恢复故障磁盘节点之前,不能在其它节点上让消费者重新连到集群并重新创建队列,如果消费者继续在其它节点上声明该队列,会得到一个 404 NOT_FOUND 错误,这样确保了当故障节点恢复后加入集群,该节点上的队列消息不会丢失,也避免了队列会在一个节点以上出现冗余的问题。
  • 在集群中的每个节点,要么是内存节点,要么是磁盘节点,如果是内存节点,会将所有的元数据信息仅存储到内存中,而磁盘节点则不仅会将所有元数据存储到内存上, 还会将其持久化到磁盘

    在单节点 RabbitMQ 上,仅允许该节点是磁盘节点,这样确保了节点发生故障或重启节点之后,所有关于系统的配置与元数据信息都会从磁盘上恢复。

    而在 RabbitMQ 集群上,至少有一个磁盘节点,也就是在集群环境中需要添加 2 台及以上的磁盘节点,这样其中一台发生故障了,集群仍然可以保持运行。其它节点均设置为内存节点,这样会让队列和交换器声明之类的操作会更加快速,元数据同步也会更加高效。

     

    三、集群部署

    为了和生产环境保持一致,我们选用CentOS7操作系统进行环境部署,分别创建 3 台虚拟机。

    # 3台服务器的IP
    197.168.24.206
    197.168.24.233
    197.168.24.234

     

    放开防火墙限制,保证 3 台服务器网络都可以互通!

     

    3.1、重新设置主机名

    由于 RabbitMQ 集群连接是通过主机名来连接服务的,必须保证各个主机名之间可以 ping 通,重新设置 3 台服务器主机名,所以需要做以下操作:

    # 修改节点1的主机名
    hostname node1

    # 修改节点2的主机名
    hostname node2

    # 修改节点3的主机名
    hostname node3

     

    编辑/etc/hosts文件,添加到在三台机器的/etc/hosts中以下内容:

    sudo vim /etc/hosts

     

    添加内容如下:

    197.168.24.206 node1
    197.168.24.233 node2
    197.168.24.234 node3

       
     

    3.2、rabbitMQ安装

    RabbitMQ 基于 erlang 进行通信,相比其它的软件,安装有些麻烦,不过本例采用rpm方式安装,任何新手都可以完成安装,过程如下!

     

    3.2.1、安装前命令准备

    输入如下命令,完成安装前的环境准备。

    yum install lsof  build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c++ kernel-devel m4 ncurses-devel tk tc xz wget vim

       
     

    3.2.2、下载 RabbitMQ、erlang、socat 的安装包

    本次下载的是RabbitMQ-3.6.5版本,采用rpm一键安装,适合新手直接上手。

    先创建一个rabbitmq目录,本例的目录路径为/usr/app/rabbitmq,然后在目录下执行如下命令,下载安装包!

    • 下载erlang
    wget www.rabbitmq.com/releases/erlang/erlang-18.3-1.el7.centos.x86_64.rpm

     

    • 下载socat
    wget http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-5.el7.lux.x86_64.rpm

     

    • 下载rabbitMQ
    wget www.rabbitmq.com/releases/rabbitmq-server/v3.6.5/rabbitmq-server-3.6.5-1.noarch.rpm

     

    最终目录文件如下:

    RabbitMQ集群高可用原理及实战部署是怎样的
     

     

    3.2.3、安装软件包

    下载完之后,按顺序依次安装软件包,这个很重要哦~

    • 安装erlang
    rpm -ivh erlang-18.3-1.el7.centos.x86_64.rpm

     

    • 安装socat
    rpm -ivh socat-1.7.3.2-5.el7.lux.x86_64.rpm

     

    • 安装rabbitmq
    rpm -ivh rabbitmq-server-3.6.5-1.noarch.rpm

     

    安装完成之后,修改rabbitmq的配置,默认配置文件在/usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin目录下。

    vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin/rabbit.app

     

    修改loopback_users节点的值!

    RabbitMQ集群高可用原理及实战部署是怎样的
     

    分别重新命令rabbit节点名称

    vim /etc/rabbitmq/rabbitmq-env.conf

     

    在文件里添加一行,如下配置!

    NODENAME=rabbit@node1

     

    其它两个节点命令也类似,然后,再保存!通过如下命令,启动服务即可!

    # 启动服务
    rabbitmq-server start &

    # 停止服务
    rabbitmqctl stop

     

    通过如下命令,查询服务是否启动成功!

    lsof -i:5672

     

    如果出现5672已经被监听,说明已经启动成功!

    RabbitMQ集群高可用原理及实战部署是怎样的
     

     

    3.2.4、启动可视化的管控台

    输入如下命令,启动控制台!

    rabbitmq-plugins enable rabbitmq_management

     

    用浏览器打开http://ip:15672,这里的ip就是 CentOS 系统的 ip,结果如下:

    RabbitMQ集群高可用原理及实战部署是怎样的
     

    账号、密码,默认为guest,如果出现无法访问,检测防火墙是否开启,如果开启将其关闭即可!

    登录之后的监控平台,界面如下:

    RabbitMQ集群高可用原理及实战部署是怎样的
     

     

    3.3、复制 Erlang cookie

    RabbitMQ 集群环境下,元数据同步基于 cookie 共享方案实现。

    在这里将 node1 的 cookie 文件复制到 node2,由于这个文件权限是 400 为方便传输,先修改权限,非必须操作,所以需要先修改 node1 中的该文件权限为 777

    chmod 777 /var/lib/rabbitmq/.erlang.cookie

     

    用 scp 拷贝到节点 2,节点 3 的操作也类似。

    scp /var/lib/rabbitmq/.erlang.cookie node2:/var/lib/rabbitmq/

     

    最后,将权限改回来

    chmod 400 /var/lib/rabbitmq/.erlang.cookie

       
     

    3.4、组成集群

    在节点 2 执行如下命令:

    # 停止rabbitmq服务
    rabbitmqctl stop_app

    # 清空节点状态
    rabbitmqctl reset

    # node2和node1构成集群,node2必须能通过node1的主机名ping通
    rabbitmqctl join_cluster rabbit@node1

    # 开启rabbitmq服务
    rabbitmqctl start_app

     

    节点 3 的操作也类似!

    在任意一台机上面查看集群状态:

    rabbitmqctl cluster_status

     

    RabbitMQ集群高可用原理及实战部署是怎样的
     
    • 第一行:表示当前节点信息
    • 第二行:表示集群中的节点成员,disc 表示这些都是磁盘节点
    • 第三行:表示正在运行的节点成员

    登录可视化管控台,可以很清晰的看到,三个服务节点已经互相关联起来了!

    RabbitMQ集群高可用原理及实战部署是怎样的
     

    如果你想将某个节点移除集群,以移除节点3为例,可以按照如下方式进行操作!

    # 首先停止要移除的节点服务
    rabbitmqctl stop

    # 移除节点3
    rabbitmqctl -n rabbit@node1 forget_cluster_node rabbit@node3

     

    如果移除之后,无法启动 rabbitMQ,删除已有 mnesia 信息!

    rm -rf /var/lib/rabbitmq/mnesia

     

    然后再次重启服务即可!

     

    3.5、设置内存节点
    #加入时候设置节点为内存节点(默认加入的为磁盘节点)
    rabbitmqctl join_cluster rabbit@node1 --ram

     

    其中--ram指的是作为内存节点,如果不加,那就默认为磁盘节点。

    如果节点在集群中已经是磁盘节点了,通过以下命令可以将节点改成内存节点:

    # 停止rabbitmq服务
    rabbitmqctl stop_app

    # 更改节点为内存节点
    rabbitmqctl change_cluster_node_type ram

    # 开启rabbitmq服务
    rabbitmqctl start_app

     

    RabbitMQ集群高可用原理及实战部署是怎样的
     

     

    3.6、镜像队列

    上面我们提到,在默认情况下,队列只会保存在其中一个节点上,当节点发生故障时,尽管所有元数据信息都可以从磁盘节点上将元数据恢复到本节点上,但是内存节点的队列消息内容就不行了,这样就会导致消息的丢失。

    RabbitMQ 很早就意识到这个问题,在 2.6 以后的版本中增加了队列冗余选项:镜像队列

    所谓镜像队列,其实就是主队列(master)依然是仅存在于一个节点上,通过关联的 rabbitMQ 服务器,从主队列同步消息到各个节点,也就是所谓的主从模式,将主队列的消息进行备份处理。

    如果主队列没有发生故障,那么其工作流程跟普通队列一样,生产者和消费者不会感知其变化,当发布消息时,依然是路由到主队列中,而主队列通过类似广播的机制,将消息扩散同步至其余从队列中,这就有点像 fanout 交换器一样。而消费者依然是从主队列中读取消息。

    一旦主队列发生故障,集群就会从最老的一个从队列选举为新的主队列,这也就实现了队列的高可用了,但我们切记不要滥用这个机制,在上面也说了,队列的冗余操作会导致不能通过扩展节点增加存储空间,而且会造成性能瓶颈。

    命令格式如下:

    rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority]

     

    参数介绍:

    -p Vhost: 可选参数,针对指定vhost下的queue进行设置
    Name: policy的名称
    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的优先级

     

    举个例子,声明名为ha-all的策略,它与名称以ha开头的队列相匹配,并将镜像配置到集群中的所有节点:

    rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'

     

    类似操作很多,具体使用可以参考官方 api。

     

    四、集群的负载均衡

    HAProxy 提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。根据官方数据,其最高极限支持10G的并发。HAProxy支持从4层至7层的网络交换,即覆盖所有的 TCP 协议。就是说,Haproxy 甚至还支持 Mysql 的均衡负载。为了实现 RabbitMQ 集群的软负载均衡,这里可以选择HAProxy。

    RabbitMQ集群高可用原理及实战部署是怎样的
     

     

    4.1、HAProxy 安装

    HAProxy 的安装也很简单,单独部署在一台服务器上,通过如下命令即可安装完成!

    yum install haproxy

     

    编辑 HAProxy 配置文件:

    vim /etc/haproxy/haproxy.cfg

     

    我们只需要在文件末尾加上如下配置即可!

    #绑定配置
    listen rabbitmq_cluster
            bind 0.0.0.0:5672
            #配置TCP模式
            mode tcp
            #加权轮询
            balance roundrobin
            #RabbitMQ集群节点配置
            server rmq_node1 197.168.24.206:5672 check inter 5000 rise 2 fall 3 weight 1
            server rmq_node2 197.168.24.233:5672 check inter 5000 rise 2 fall 3 weight 1
            server rmq_node3 197.168.24.234:5672 check inter 5000 rise 2 fall 3 weight 1

    #haproxy监控页面地址
    listen monitor
            bind 0.0.0.0:8100
            mode http
            option httplog
            stats enable
            stats uri /stats
            stats refresh 5s

     

    绑定配置参数说明:

    • bind:这里定义了客户端连接连接 IP 地址和端口号,用于客户端连接
    • balance roundrobin:表示加权轮询负载均衡算法

    RabbitMQ 集群节点配置说明:

    • server rmq_node1:定义HAProxy内RabbitMQ服务的标识
    • 197.168.24.206:5672:标识了后端RabbitMQ的服务地址
    • check inter 5000:表示每隔多少毫秒检查RabbitMQ服务是否可用,示例参数值为 5000
    • rise 2:表示 RabbitMQ 服务在发生故障之后,需要多少次健康检查才能被再次确认可用,示例参数值为 2
    • fall 2:表示需要经历多少次失败的健康检查之后,HAProxy 才会停止使用此RabbitMQ服务,示例参数值为 2
    • weight 1:表示权重比例,值越低,会优先进行数据分配,示例参数值为 1

    启动 HAProxy:

    /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg

     

    登录http://ip:8100/statsweb 管理界面,即可进行监控查看!

    RabbitMQ集群高可用原理及实战部署是怎样的
     

     

    五、Java 客户端使用

    如果是配置了 HAProxy 代理服务器,可以直接使用 HAProxy 代理服务器地址即可!

     //ConnectionFactory创建MQ的物理连接
    connectionFactory = new ConnectionFactory();
    connectionFactory.setHost("197.168.24.207");  //代理服务器地址
    connectionFactory.setPort(5672);          //代理服务器端口
    connectionFactory.setUsername("admin");  //guest只能在本机进行访问,通过代理服务器发送消息时需要重新建立用户
    connectionFactory.setPassword("admin");  //guest
    connectionFactory.setVirtualHost("/");    //虚拟主机

     

    如果没有代理服务器,使用SpringCachingConnectionFactory类进行配置。

    SpringBoot项目为例,配置文件如下:

    spring.rabbitmq.addresses=197.168.24.206:5672,197.168.24.233:5672,197.168.24.234:5672
    spring.rabbitmq.username=guest
    spring.rabbitmq.password=guest
    spring.rabbitmq.virtual-host=/

     

    RabbitConfig配置类如下:

    @Configuration
    public class RabbitConfig {

        /**
         * 初始化连接工厂
         * @param addresses
         * @param userName
         * @param password
         * @param vhost
         * @return
         */
        @Bean
        ConnectionFactory connectionFactory(@Value("${spring.rabbitmq.addresses}") String addresses,
                                            @Value("${spring.rabbitmq.username}") String userName,
                                            @Value("${spring.rabbitmq.password}") String password,
                                            @Value("${spring.rabbitmq.virtual-host}") String vhost) {
            CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
            connectionFactory.setAddresses(addresses);
            connectionFactory.setUsername(userName);
            connectionFactory.setPassword(password);
            connectionFactory.setVirtualHost(vhost);
            return connectionFactory;
        }

        /**
         * 重新实例化 RabbitAdmin 操作类
         * @param connectionFactory
         * @return
         */
        @Bean
        public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
            return new RabbitAdmin(connectionFactory);
        }

        /**
         * 重新实例化 RabbitTemplate 操作类
         * @param connectionFactory
         * @return
         */
        @Bean
        public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
            RabbitTemplate rabbitTemplate=new RabbitTemplate(connectionFactory);
            //数据转换为json存入消息队列
            rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
            return rabbitTemplate;
        }

    }

    关于RabbitMQ集群高可用原理及实战部署是怎样的就分享到这里了,希望

    内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/133180.html

    (0)

    相关推荐

    • 怎么为SQL Server快照snapshot DB建立login访问

      技术怎么为SQL Server快照snapshot DB建立login访问这篇文章主要讲解了“怎么为SQL Server快照snapshot DB建立login访问”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟

      攻略 2021年11月9日
    • 香港多IP香港多IP服务器可以做游戏代理吗

      技术香港多IP香港多IP服务器可以做游戏代理吗很多玩家候经常会发现无论是steam还是psn虽然游戏下载升级很快但是联机的时候质量很差,那么如何解决这一问题呢,不少用户想到利用游戏加速器,但是现在很多游戏加速器都推出了V

      礼包 2021年10月22日
    • 走之旁是几画,左边的“边”走之旁是几划

      技术走之旁是几画,左边的“边”走之旁是几划一、走之旁有三画走之旁是几画,拼音是chuò ,同“辵”。用作偏旁。俗称“走之旁”,简称“走之”。;二、走之旁的字有进、还、过、边、远、选、连、逃、运、这、遇、遍、追、速、送、道

      生活 2021年10月26日
    • C语言是怎样输出唯一的子串

      技术C语言是怎样输出唯一的子串C语言是怎样输出唯一的子串,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 题目描述给一个字符串,求长度为m的所有不重复的子

      攻略 2021年12月8日
    • 如何使用Docker和Traefik搭建WordPress

      技术如何使用Docker和Traefik搭建WordPress这篇文章主要为大家展示了“如何使用Docker和Traefik搭建WordPress”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一

      攻略 2021年11月19日
    • 0337-打家劫舍III

      技术0337-打家劫舍III 0337-打家劫舍III在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一

      礼包 2021年12月3日