RabbitMQ 集群

作者: YMeng_Zhang | 来源:发表于2021-11-08 17:45 被阅读0次

    RabbitMQ 集群

    RabbitMQ 有 3 种模式,其中 2 种是集群模式。

    单一模式:即单机情况不做集群,就单独运行一个 RabbitMQ 而已。

    普通模式:默认模式,以两个节点(A、B)为例来进行说明:

    • 当消息进入 A 节点的 Queue 后,Consumer 从 B 节点消费时,RabbitMQ 会在 A 和 B 之间创建临时通道进行消息传输,把 A 中的消息实体取出并经过通过交给 B 发送给 Consumer。
    • 当 A 故障后,B 就无法取到 A 节点中未消费的消息实体;如果做了消息持久化,那么得等 A 节点恢复,然后才可被消费;如果没有持久化的话,就会产生消息丢失的现象。

    镜像模式 :经典的 Mirror 镜像模式,保证数据不丢失:

    • 高可靠性解决方案,主要就是实现数据的同步,一般来讲是 2 - 3 个节点实现数据同步。
    • 对于 100% 数据可靠性解决方案,一般是采用 3 个节点。
    • 在实际工作中也是用得最多的,并且实现非常的简单,一般互联网大厂都会构建这种镜像集群模式。

    另外,还有主备模式,远程模式,多活模式等等。

    集群搭建

    前置条件:准备两台 linux(192.168.186.128 和 192.168.186.129),并安装好 RabbitMQ。

    1. 修改映射文件 vim /etc/hosts 。
    1 号服务器:
    
    127.0.0.1 A   localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1       A   localhost localhost.localdomain localhost6 localhost6.localdomain6
    
    192.168.186.128 A
    192.168.186.129 B
    

    2 号服务器:

    127.0.0.1 A   localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1       A   localhost localhost.localdomain localhost6 localhost6.localdomain6
    
    192.168.186.128 A
    192.168.186.129 B
    

    修改完 hosts 文件后,需要重启 Linux 服务器 reboot,否则配置不生效。

    1. 相互通信,cookie 必须保持一致,同步 RabbitMQ 的 cookie 文件:跨服务器拷贝 .erlang.cookie(隐藏文件,使用 ls -all 显示)。
    scp /var/lib/rabbitmq/.erlang.cookie 192.168.186.129:/var/lib/rabbitmq/
    

    修改 cookie 文件,要重启 linux 服务器 reboot。

    1. 防火墙开放 epmd 端口 4369,启动 RabbitMQ 服务。
    firewall-cmd --zone=public --add-port=4369/tcp --permanent
    firewall-cmd --reload
    systemctl start rabbitmq-server
    
    1. 加入集群节点,节点 A 加入 节点 B,或者节点 B 加入节点 A 都可以:
    [root@A ~]# rabbitmqctl stop_app
    Stopping rabbit application on node rabbit@A ...
    [root@A ~]# rabbitmqctl join_cluster rabbit@B
    Clustering node rabbit@A with rabbit@B
    [root@A ~]# rabbitmqctl start_app
    Starting node rabbit@A ...
    
    1. 查看节点状态:
    rabbitmqctl cluster_status
    
    1. 查看管理端

    搭建集群结构之后,之前创建的交换机、队列、用户都属于单一结构,在新的集群环境中是不能用的。

    所以在新的集群中重新手动添加用户即可(任意节点添加,所有节点共享)。

    [root@A ~]# rabbitmqctl add_user zm 123456
    Adding user "zm" ...
    [root@A ~]# rabbitmqctl set_user_tags zm administrator
    Setting tags for user "zm" to [adminstrator] ...
    [root@A ~]# rabbitmqctl set_permissions -p "/" zm ".*" ".*" ".*"
    Setting permissions for user "zm" in vhost "/" ...
    [root@A ~]# rabbitmqctl list_users
    Listing users ...
    user    tags
    zm  [administrator]
    guest   [administrator]
    

    访问 http://192.168.186.128:15672http://192.168.186.129:15672,两个节点共享用户。

    注意:当节点脱离集群还原成单一结构后,交换机,队列和用户等数据都会重新回来。

    此时,RabbitMQ 的集群搭建完毕,但是默认采用的模式为“普通模式”,可靠性不高。

    镜像模式

    将所有队列设置为镜像队列,即队列会被复制到各个节点,各个节点状态一致。

    语法:set_policy {NAME} {PATTERN} {DEFINITION}
    其中:
    NAME - 策略名,可自定义

    PATTERN - 队列的匹配模式(正则表达式)

    • ^ 可以使用正则表达式,比如 ^queue_ 表示对队列名称以 queue_ 开头的所有队列进行镜像,而 ^ 会匹配所有的队列。

    DEFINITION - 镜像定义,包括三个部分 ha-mode, ha-params, ha-sync-mode

    • ha-mode - high available 高可用模式,指镜像队列的模式,有效值为 all/exactly/nodes;当前策略模式为 all,即复制到所有节点,包含新增节点。all 表示在集群中所有的节点上进行镜像;exactly 表示在指定个数的节点上进行镜像,节点的个数由 ha-params 指定;nodes 表示在指定的节点上进行镜像,节点名称通过 ha-params 指定。
    • ha-params - ha-mode 模式需要用到的参数。
    • ha-sync-mode - 进行队列中消息的同步方式,有效值为 automatic 和 manual。
    [root@A ~]# rabbitmqctl set_policy policy_renda "^" '{"ha-mode":"all"}'
    Setting policy "policy_zm" for pattern "^" to "{"ha-mode":"all"}" with priority "0" for vhost "/" ...
    

    通过管理端 Admin -> Policies -> Add / update a policy 设置镜像策略。

    设置好镜像模式后,在节点 A 增加了队列后,节点 B 也可以看到新增的队列。

    在 RabbitMQ 管理界面 Admin -> Virtual Hosts -> Add a new virtual host 创建虚拟主机 /zm;

    使用 Spring 整合的 RabbitMQ 重新测试发送和接受消息;在其中一个节点使用命令 rabbitmqctl stop_app 停掉,再测试,仍然可以发送和接受消息。

    HAProxy 实现镜像队列的负载均衡

    虽然在程序中访问 A 服务器,可以实现消息的同步,但都是 A 服务器在接收消息,A 太累;是否可以负载均衡,A 和 B 轮流接收消息,再镜像同步。

    HAProxy 简介

    HA - High Available 高可用,Proxy - 代理。

    HAProxy 是一款提供高可用性,负载均衡,并且基于 TCP 和 HTTP 应用的代理软件。

    HAProxy 完全免费。

    HAProxy 可以支持数以万计的并发连接。

    HAProxy 可以简单又安全的整合进架构中,同时还保护 Web 服务器不被暴露到网络上。

    生产者 -- 投递消息 --> HAProxy
    消费者 -- 订阅消息 --> HAProxy

    HAProxy ---> [MQ Node 1, MQ Node 2, MQ Node 3]

    HAProxy 与 Nginx

    OSI - Open System Interconnection 开放式系统互联,是把网络通信的工作分为 7 层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。

    Nginx 的优点:

    • 工作在 OSI 第 7 层,可以针对 http 应用做一些分流的策略。
    • Nginx 对网络的依赖非常小,理论上能 ping 通就就能进行负载功能,屹立至今的绝对优势。
    • Nginx 安装和配置比较简单,测试起来比较方便。
    • Nginx 不仅仅是一款优秀的负载均衡器 / 反向代理软件,它同时也是功能强大的 Web 应用服务器。

    HAProxy 的优点:

    • 工作在网络 4 层和 7 层,支持 TCP 与 Http 协议。
    • 它仅仅就只是一款负载均衡软件;单纯从效率上来讲 HAProxy 更会比 Nginx 有更出色的负载均衡速度,在并发处理上也是优于 Nginx 的。
    • 支持 8 种负载均衡策略 ,支持心跳检测。

    性能上 HAProxy 胜,但是功能性和便利性上 Nginx 胜。

    对于 Http 协议,HAProxy 处理效率比 Nginx 高;所以,没有特殊要求的时候或者一般场景,建议使用 Haproxy 来做 Http 协议负载;如果是 Web 应用,建议使用 Nginx。

    需要结合使用场景的特点来进行合理地选择。

    安装和配置

    HAProxy 下载:http://www.haproxy.org/download/1.8/src/haproxy-1.8.12.tar.gz

    • 上传到第三台 Linux 服务器(192.168.186.130)中并解压:
    tar -zxvf haproxy-1.8.12.tar.gz
    
    • make 时需要使用 TARGET 指定内核及版本:
    [root@localhost haproxy-1.8.12]# uname -r
    3.10.0-229.el7.x86_64
    

    查看目录下的 README 文件 less /opt/haproxy-1.8.12/README 可知需要根据内核版本选择编译参数:

    ...
    To build haproxy, you have to choose your target OS amongst the following ones
    and assign it to the TARGET variable :
    
      - linux22     for Linux 2.2
      - linux24     for Linux 2.4 and above (default)
      - linux24e    for Linux 2.4 with support for a working epoll (> 0.21)
      - linux26     for Linux 2.6 and above
      - linux2628   for Linux 2.6.28, 3.x, and above (enables splice and tproxy)
      - solaris     for Solaris 8 or 10 (others untested)
      - freebsd     for FreeBSD 5 to 10 (others untested)
      - netbsd      for NetBSD
      - osx         for Mac OS/X
      - openbsd     for OpenBSD 5.7 and above
      - aix51       for AIX 5.1
    ...
    
    • 进入目录,编译和安装:
    cd /opt/haproxy-1.8.12/
    make TARGET=linux2628 PREFIX=/usr/local/haproxy
    make install PREFIX=/usr/local/haproxy
    
    • 安装成功后,查看版本:
    [root@localhost haproxy-1.8.12]# /usr/local/haproxy/sbin/haproxy -v
    HA-Proxy version 1.8.12-8a200c7 2018/06/27
    Copyright 2000-2018 Willy Tarreau <willy@haproxy.org>
    
    • 配置启动文件,复制 haproxy 文件到 /usr/sbin 目录下 ,复制 haproxy 脚本,到 /etc/init.d 目录下:
    cp /usr/local/haproxy/sbin/haproxy /usr/sbin/
    cp /opt/haproxy-1.8.12/examples/haproxy.init /etc/init.d/haproxy
    chmod 755 /etc/init.d/haproxy
    
    • 创建系统账号:
    useradd -r haproxy
    
    • haproxy.cfg 配置文件需要自行创建:
    mkdir /etc/haproxy
    vim /etc/haproxy/haproxy.cfg
    
    • 添加配置信息到 haproxy.cfg:
    # 全局配置
    global
        # 设置日志
        log 127.0.0.1 local0 info
        # 当前工作目录
        chroot /usr/local/haproxy
        # 用户与用户组
        user haproxy
        group haproxy
        # 运行进程 ID
        uid 99
        gid 99
        # 守护进程启动
        daemon
        # 最大连接数
        maxconn 4096
    
    # 默认配置
    defaults
        # 应用全局的日志配置
        log global
        # 默认的模式 mode {tcp|http|health},TCP 是 4 层,HTTP 是 7 层,health 只返回 OK
        mode tcp
        # 日志类别 tcplog
        option tcplog
        # 不记录健康检查日志信息
        option dontlognull
        # 3 次失败则认为服务不可用
        retries 3
        # 每个进程可用的最大连接数
        maxconn 2000
        # 连接超时
        timeout connect 5s
        # 客户端超时 30 秒,ha 就会发起重新连接
        timeout client 30s
        # 服务端超时 15 秒,ha 就会发起重新连接
        timeout server 15s
    
    # 绑定配置
    listen rabbitmq_cluster
        bind 192.168.186.130:5672
        # 配置 TCP 模式
        mode tcp
        # 简单的轮询
        balance roundrobin
        # RabbitMQ 集群节点配置,每隔 5 秒对 mq 集群做检查,2 次正确证明服务可用,3 次失败证明服务不可用
        server A 192.168.186.128:5672 check inter 5000 rise 2 fall 3
        server B 192.168.186.129:5672 check inter 5000 rise 2 fall 3
    
    # haproxy 监控页面地址
    listen monitor
        bind 192.168.186.130:8100
        mode http
        option httplog
        stats enable
        # 监控页面地址 http://192.168.186.130:8100/monitor
        stats uri /monitor
        stats refresh 5s
    
    • 启动 HAProxy:
    service haproxy start
    
    • 开放对应的防火墙端口:
    firewall-cmd --zone=public --add-port=5672/tcp --permanent
    firewall-cmd --zone=public --add-port=8100/tcp --permanent
    firewall-cmd --reload
    

    项目发消息,只需要将服务器地址修改为 192.168.186.130 即可,其余不变。

    这样,所有的请求都会交给 HAProxy,然后它会负载均衡地发给每个 RabbitMQ 服务器。

    KeepAlived 搭建高可用的 HAProxy 集群

    如果 HAProxy 服务器宕机,RabbitMQ 服务器就不可用了,所以对 HAProxy 也要做高可用的集群。

    概述

    Keepalived 是 Linux 的轻量级别的高可用热备解决方案。

    Keepalived 的作用是检测服务器的状态,它根据 TCP / IP 参考模型的第三层、第四层、第五层交换机制检测每个服务节点的状态,如果有一台 web 服务器宕机,或工作出现故障,Keepalived 将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工作正常后 Keepalived 自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。

    Keepalived 基于 VRRP - Virtual Router Redundancy Protocol 虚拟路由冗余协议协议;VRRP 是一种主备(主机和备用机)模式的协议,通过 VRRP 可以在网络发生故障时透明的进行设备切换而不影响主机之间的数据通信。

    两台主机之间生成一个虚拟的 ip,称为漂移 ip,漂移 ip 由主服务器承担,一但主服务器宕机,备份服务器就会抢夺漂移 ip,继续工作,有效的解决了群集中的单点故障。

    KeepAlived 将多台路由器设备虚拟成一个设备,对外提供统一 ip(Virtual IP)。

    生产者 -- 投递消息 --> KeepAlived
    消费者 -- 订阅消息 --> KeepAlived

    HAProxy 1 --> 主机 1 --> KeepAlived 虚拟 IP
    HAProxy 2 --> 主机 2 --> KeepAlived 虚拟 IP

    安装 KeepAlived
    • 修改映射文件 vim /etc/hosts 。

    3 号服务器 192.168.186.130:

    127.0.0.1 C   localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1       C   localhost localhost.localdomain localhost6 localhost6.localdomain6
    
    192.168.186.128 A
    192.168.186.129 B
    192.168.186.130 C
    192.168.186.131 D
    

    4 号服务器 192.168.186.131:

    127.0.0.1 D   localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1       D   localhost localhost.localdomain localhost6 localhost6.localdomain6
    
    192.168.186.128 A
    192.168.186.129 B
    192.168.186.130 C
    192.168.186.131 D
    

    注意:修改完 hosts 文件后,需要重启 Linux 服务器 reboot,否则配置不生效。

    • 重新启动后,需要启动 haproxy:
    service haproxy start
    
    • 主机 C 和主机 D 都安装 keepalived:
    yum install -y keepalived
    
    • 主机 C 修改配置文件(删掉内容,重新创建):
    rm -rf /etc/keepalived/keepalived.conf
    vim /etc/keepalived/keepalived.conf
    ! Configuration File for keepalived
    
    global_defs {
        # 非常重要,标识本机的 hostname
        router_id C
    }
    
    vrrp_script chk_haproxy {
        # 执行的脚本位置
        script "/etc/keepalived/haproxy_check.sh"
        # 检测时间间隔
        interval 2
        # 如果条件成立则权重减 20
        weight -20
    }
    
    vrrp_instance VI_1 {
        # 非常重要,标识主机,备用机 131 改为 BACKUP
        state MASTER
        # 非常重要,网卡名(ifconfig 查看)
        interface ens33
        # 非常重要,自定义,虚拟路由 ID 号(主备节点要相同)
        virtual_router_id 66
        # 优先级(0-254),一般主机的大于备机
        priority 100
        # 主备信息发送间隔,两个节点必须一致,默认 1 秒
        advert_int 1
        # 认证匹配,设置认证类型和密码,MASTER 和 BACKUP 必须使用相同的密码才能正常通信
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        track_script {
            # 检查 haproxy 健康状况的脚本
            chk_haproxy
        }
        # 简称 “VIP”
        virtual_ipaddress {
            # 非常重要,虚拟 ip,可以指定多个,以后连接 mq 就用这个虚拟ip
            192.168.186.66/24
        }
    }
    # 虚拟 ip 的详细配置
    virtual_server 192.168.186.66 5672 {
        # 健康检查间隔,单位为秒
        delay_loop 6
        # lvs 调度算法 rr|wrr|lc|wlc|lblc|sh|dh
        lb_algo rr
        # 负载均衡转发规则。一般包括 DR, NAT, TUN 3 种
        lb_kind NAT
        # 转发协议,有 TCP 和 UDP 两种,一般用 TCP
        protocol TCP
            # 本机的真实 ip
            real_server 192.168.186.130 5672 {
            # 默认为 1, 失效为 0
            weight 1
        }
    }
    
    • 主机 C 创建执行脚本 vim /etc/keepalived/haproxy_check.sh
    #!/bin/bash
    COUNT=`ps -C haproxy --no-header |wc -l`
    if [ $COUNT -eq 0 ];then
        /usr/local/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg
        sleep 2
        if [ `ps -C haproxy --no-header |wc -l` -eq 0 ];then
            killall keepalived
        fi
    fi
    

    Keepalived 组之间的心跳检查并不能察觉到 HAproxy 负载是否正常,所以需要使用此脚本。在 Keepalived 主机上,开启此脚本检测 HAproxy 是否正常工作,如正常工作,记录日志。如进程不存在,则尝试重启 HAproxy ,2 秒后检测,如果还没有,则关掉主机的 Keepalived ,此时备 Keepalived 检测到主 Keepalived 挂掉,接管 VIP,继续服务。

    • 主机 C 给脚本文件增加执行权限:
    chmod +x /etc/keepalived/haproxy_check.sh
    

    此时,安装完毕,按照上面的步骤就可以安装第二台主机 D 了(服务器 hostname 和 ip 注意要修改)。

    service keepalived start | stop | status | restart
    
    • 启动 keepalived(两台都启动):
    service keepalived start
    
    • 查看状态:
    ps -ef | grep haproxy
    ps -ef | grep keepalived
    
    • 查看 ip 情况 ip addr 或 ip a。

    启动 keepalived 前的情况:

    [root@C keepalived]# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
        link/ether 00:0c:29:ac:93:50 brd ff:ff:ff:ff:ff:ff
        inet 192.168.186.130/24 brd 192.168.186.255 scope global ens33
           valid_lft forever preferred_lft forever
        inet6 fe80::20c:29ff:feac:9350/64 scope link 
           valid_lft forever preferred_lft forever
    

    启动 keepalived 后的情况:

    [root@C keepalived]# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
        link/ether 00:0c:29:ac:93:50 brd ff:ff:ff:ff:ff:ff
        inet 192.168.186.130/24 brd 192.168.186.255 scope global ens33
           valid_lft forever preferred_lft forever
        inet 192.168.186.66/24 scope global secondary ens33
           valid_lft forever preferred_lft forever
        inet6 fe80::20c:29ff:feac:9350/64 scope link 
           valid_lft forever preferred_lft forever
    

    可以看到 ens33 网卡还多绑定了一个 IP 地址。

    常见的网络错误:子网掩码、网关等信息要一致。

    测试 vip 和端口一起是否能提供服务

    在 192.168.186.128,A 服务器上测试。

    在服务器 A 执行 curl 192.168.186.130:5672curl 192.168.186.66:5672 都能正常返回 AMPQ,说明安装成功。

    测试 ip 漂移的规则

    使用 ip addr 或 ip a 查看虚拟 ip。

    刚开始时,C 和 D 都启动了 KeepAlived;C 是主机,所以虚拟 ip 在主机 C,表现为主机 C 显示 inet 192.168.186.66/24,而备机 D 不显示。

    然后,停止主机 C 的 keepalived service keepalived stop,虚拟 ip 漂移到 D 节点,D 节点执行 ip a 可以看到 inet 192.168.186.66/24,而主机 C 却不显示。

    接着,重新启动 C 节点的 Keepalived,虚拟 ip 依旧在 D 节点,并不会由于 C 的回归而回归。

    最后,停止 D 的 Keepalived,虚拟 ip 再漂移回 C 节点。

    测试项目发消息

    消费者或生产者 -- 漂移 IP 66 --> KeepAlived 服务 --> [HAProxy 服务器C 130, HAProxy 服务器D 131]

    HAProxy 服务器C 130 -- 负载均衡 --> [MQ 服务器A 128, MQ 服务器B 129]
    HAProxy 服务器D 130 -- 负载均衡 --> [MQ 服务器A 128, MQ 服务器B 129]

    测试单个 RabbitMQ 服务器:将服务器地址修改为 192.168.186.128,其余不变。

    测试 HAProxy 实现多个 RabbitMQ 服务器负载均衡:将服务器地址修改为 192.168.186.130,其余不变。

    测试 KeepAlived 实现的高可用的 HAProxy 集群:将服务器地址修改为 KeepAlived 的虚拟 IP 192.168.186.66,其余不变。

    相关文章

      网友评论

        本文标题:RabbitMQ 集群

        本文链接:https://www.haomeiwen.com/subject/idzuzltx.html