rabbitMQ+ha高可用集群搭建
young / / / 阅读量

(一) 功能和原理

设计集群的目的
• 允许消费者和生产者在RabbitMQ节点崩溃的情况下继续运行
• 通过增加更多的节点来扩展消息通信的吞吐量

1 集群配置方式

RabbitMQ可以通过三种方法来部署分布式集群系统,分别是:cluster,federation,shovel
• cluster:
• 不支持跨网段,用于同一个网段内的局域网
• 可以随意的动态增加或者减少

• 节点之间需要运行相同版本的RabbitMQ和Erlang
• federation:应用于广域网,允许单台服务器上的交换机或队列接收发布到另一台服务器上交换机或队列的消息,可以是单独机器或集群。federation队列类似于单向点对点连接,消息会在联盟队列之间转发任意次,直到被消费者接受。通常使用federation来连接internet上的中间服务器,用作订阅分发消息或工作队列。
• shovel:连接方式与federation的连接方式类似,但它工作在更低层次。可以应用于广域网。

2 节点类型

• RAM node:内存节点将所有的队列、交换机、绑定、用户、权限和vhost的元数据定义存储在内存中,好处是可以使得像交换机和队列声明等操作更加的快速。
• Disk node:将元数据存储在磁盘中,单节点系统只允许磁盘类型的节点,防止重启RabbitMQ的时候,丢失系统的配置信息。
问题说明: RabbitMQ要求在集群中至少有一个磁盘节点,所有其他节点可以是内存节点,当节点加入或者离开集群时,必须要将该变更通知到至少一个磁盘节点。如果集群中唯一的一个磁盘节点崩溃的话,集群仍然可以保持运行,但是无法进行其他操作(增删改查),直到节点恢复。
解决方案:设置两个磁盘节点,至少有一个是可用的,可以保存元数据的更改。

3 Erlang Cookie

Erlang Cookie是保证不同节点可以相互通信的密钥,要保证集群中的不同节点相互通信必须共享相同的Erlang Cookie。具体的目录存放在/var/lib/rabbitmq/.erlang.cookie。
说明: 这就要从rabbitmqctl命令的工作原理说起,RabbitMQ底层是通过Erlang架构来实现的,所以rabbitmqctl会启动Erlang节点,并基于Erlang节点来使用Erlang系统连接RabbitMQ节点,在连接过程中需要正确的Erlang Cookie和节点名称,Erlang节点通过交换Erlang Cookie以获得认证。

4 镜像队列

功能和原理
RabbitMQ的Cluster集群模式一般分为两种,普通模式和镜像模式。
• 普通模式:默认的集群模式,以两个节点(rabbit01、rabbit02)为例来进行说明。对于Queue来说,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02两个节点仅有相同的元数据,即队列的结构。当消息进入rabbit01节点的Queue后,consumer从rabbit02节点消费时,RabbitMQ会临时在rabbit01、rabbit02间进行消息传输,把A中的消息实体取出并经过B发送给consumer。所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。当rabbit01节点故障后,rabbit02节点无法取到rabbit01节点中还未消费的消息实体。如果做了消息持久化,那么得等rabbit01节点恢复,然后才可被消费;如果没有持久化的话,就会产生消息丢失的现象。
• 镜像模式:将需要消费的队列变为镜像队列,存在于多个节点,这样就可以实现RabbitMQ的HA高可用性。作用就是消息实体会主动在镜像节点之间实现同步,而不是像普通模式那样,在consumer消费数据时临时读取。缺点就是,集群内部的同步通讯会占用大量的网络带宽。
在上述的集群中,如果某个节点挂掉,整个集群还是可以正常工作的,但是挂掉的那个节点的消息就清空了。这种情况在生产环境中是不可接受的,所以需要用到镜像功能,也就是主从配置。
在集群中的任意一台主机上执行:
rabbitmqctl set_policy ha-all “^” ‘{“ha-mode”:”all”}’
意思表示所有queue都会复制到各个节点 [“^”匹配所有]

(二) RabbitMQ Cluster 配置

1 单机多节点部署

rabbitmq安装
在启动RabbitMQ节点之后,服务器默认的节点名称是Rabbit和监听端口5672,如果想在同一台机器上启动多个节点,那么其他的节点就会因为节点名称和端口与默认的冲突而导致启动失败,可以通过设置环境变量来实现,具体方法如下:

首先在机器上设置两个节点rabbit和rabbit1

RABBITMQ_NODE_PORT=5672 RABBITMQ_NODENAME=rabbit rabbitmq-server -detached 
RABBITMQ_NODE_PORT=5673 RABBITMQ_NODENAME=rabbit1 rabbitmq-server -detached

或者通过添加/etc/rabbitmq/rabbitmq-env.conf文件来进行设置:

NODE_PORT=5672
NODENAME=rabbit
NODE_PORT=5673
NODENAME=rabbit1

停止实例

rabbitmqctl -n rabbit1 stop
rabbitmqctl -n rabbit1 join_cluster rabbit

//将rabbit_01添加到集群节点rabbit中去

rabbitmqctl cluster_status

//查看集群节点的状态

rabbitmqctl -n rabbit_01@localhost start_app

//启动rabbit_01节点的应用
//可以看到如下信息,说明节点添加成功,表明都是磁盘类型的节点

Cluster status of node rabbit@localhost ...
[{nodes,[{disc,[rabbit@localhost,rabbit_01@localhost]}]},
 {running_nodes,[rabbit@localhost]},
 {cluster_name,<<"rabbit@localhost">>},
 {partitions,[]},
 {alarms,[{rabbit@localhost,[]}]}]

2 多机多节点部署

rabbitmq安装
不同于单机多节点的情况,在多机环境,如果要在cluster集群内部署多个节点,需要注意两个方面:
• 保证需要部署的这几个节点在同一个局域网内
• 需要有相同的Erlang Cookie,否则不能进行通信,为保证cookie的完全一致,采用从一个节点copy的方式
环境介绍:
RabbitMQ节点 IP地址 工作模式 操作系统
rabbit1 192.168.200.179 DISK CentOS 6.8 – 64位
rabbit2 192.168.200.180 DISK CentOS 6.8 – 64位
rabbit3 192.168.200.181 DISK CentOS 6.8 – 64位
cluster部署过程:
rabbit部署方法:点击
• 局域网配置
分别在三个节点的/etc/hosts下设置相同的配置信息
192.168.200.179 rabbit1
192.168.200.180 rabbit2
192.168.200.181 rabbit3
设置不同节点间同一认证的Erlang Cookie
采用从主节点copy的方式保持Cookie的一致性

[root@rabbit1 rabbitMQ]# scp /root/.erlang.cookie root@192.168.200.180:/root/
.erlang.cookie
[root@rabbit1 rabbitMQ]# scp /root/.erlang.cookie root@192.168.200.181:/root/
.erlang.cookie

• 使用 -detached运行各节点

rabbitmqctl stop
rabbitmq-server -detached

查看各节点的状态

[root@rabbit1 rabbitMQ]# rabbitmqctl cluster_status
[root@rabbit1 rabbitMQ]# rabbitmqctl cluster_status 
[root@rabbit1 rabbitMQ]# rabbitmqctl cluster_status 

为了连接集群中的三个节点,我们把rabbit2和rabbit3节点加入到rabbit1节点集群
首先,在rabbit@c1的簇中加入rabbit@c2
  1、停止rabbir@c2的rabbitmq应用程序,
  2、加入rabbit@c1集群
  3、然后启动RabbitMQ程序
注意:加入集群会隐式重置节点,从而删除此节点上以前存在的所有资源和数据

[root@rabbit2 ~]# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbit2 ...
[root@rabbit2 ~]# rabbitmqctl join_cluster rabbit@rabbit1
Clustering node rabbit@rabbit2 with rabbit@rabbit1
[root@rabbit2 ~]# rabbitmqctl start_app
Starting node rabbit@rabbit2 ...

[root@rabbit3 ~]# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbit3 ...
[root@rabbit3 ~]# rabbitmqctl join_cluster rabbit@rabbit1
Clustering node rabbit@rabbit3 with rabbit@rabbit1
[root@rabbit3 ~]# rabbitmqctl start_app
Starting node rabbit@rabbit3 ...

现在我们在rabbit1、rabbit2、rabbit3任意一个节点上查看集群状态,我们可以看到这两个节点加入了一个集群

[root@rabbit1 rabbitmq]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit3,rabbit@rabbit2,rabbit@rabbit1]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit3,[]},{rabbit@rabbit2,[]},{rabbit@rabbit1,[]}]}]

启用集群高可用
在 RabbitMQ Cluster 每个节点执行:

rabbitmqctl set_policy ha-all "" '{"ha-mode":"all","ha-sync-mode":"automatic"}'

启用 RabbitMQ 组件
在 RabbitMQ Cluster 每个节点执行:

rabbitmq-plugins enable rabbitmq_management

添加用户
在 RabbitMQ Cluster 每个节点执行:

[root@gitserver ~]# rabbitmqctl add_user root root
[root@gitserver ~]# rabbitmqctl set_user_tags root administrator
[root@gitserver ~]# rabbitmqctl set_permissions -p / root '.*' '.*' '.*'

3 集群移除节点

当节点不再是节点的一部分时,需要从集群中明确地删除节点。我们首先从集群中删除rabbit@rabbit3,并将其返回到独立操作
在rabbit@rabbit3上:
  1、我们停止RabbitMQ应用程序,
  2、重置节点
  3、重新启动RabbitMQ应用程序

[root@rabbit3 ~]# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbit3 ...

[root@rabbit3 ~]# rabbitmqctl reset
Resetting node rabbit@rabbit3 ...

[root@rabbit3 ~]# rabbitmqctl start_app
Starting node rabbit@rabbit3 ...
 completed with 0 plugins.

(三) HA配置

安装 haproxy

上传haproxy安装包

/web/soft/haproxy #安装目录
tar -xf haproxy-1.7.tar.gz && cd ./haproxy-1.7
make TARGET=linux2628 ARCH=x86_64 PREFIX=$Hadir
make install PREFIX=/web/soft/haproxy

配置 haproxy

vim /web/soft/haproxy/haproxy.cfg

global
    log    127.0.0.1 local3
    nbproc 1
    maxconn    4000
#    nbproc    2
    daemon
#    debug
#    quiet

defaults
log global
log    127.0.0.1 local3
mode http
mode http
timeout connect 5000ms #连接超时
timeout client 30000ms #连接超时
timeout server 30000ms #连接超时
option  httpclose # 每次请求完毕后主动关闭http通道
option  redispatch      # serverId对应的服务器挂掉后,强制定向到其他健康的服务器

#配置haproxy web监控,查看统计信息
listen http_front
    bind 0.0.0.0:8100
    stats refresh 30s           #统计页面自动刷新时间  
    stats uri /haproxy?stats            #统计页面url  
    stats realm Haproxy Manager #统计页面密码框上提示文本  
    stats auth launcher:Mq2018      #统计页面用户名和密码设置  
    stats hide-version         #隐藏统计页面上HAProxy的版本信息


listen rabbit_admin
    bind 0.0.0.0:35672
    server rabbitmq1 192.168.200.179:15672
    server rabbitmq2 192.168.200.180:15672
    server rabbitmq3 192.168.200.181:15672

listen rabbitmq_cluster
    bind 0.0.0.0:35673
    #简单的轮询
    option tcplog
    mode tcp
    timeout client  3h
    timeout server  3h
    option          clitcpka
    balance roundrobin
    #rabbitmq集群节点配置
    server rabbitmq1 192.168.200.179:5672 check inter 5000 rise 2 fall 2
    server rabbitmq2 192.168.200.180:5672 check inter 5000 rise 2 fall 2
    server rabbitmq3 192.168.200.181:5672 check inter 5000 rise 2 fall 2
##服务器定义(check指健康状况检查,inter 2000指检测频率;rise 2指从离线状态转换至正常状态需要成功检查的次数;fall 2指失败2次即认为服务器不可用)

启动 haproxy

/web/soft/haproxy/sbin/haproxy -f /web/soft/haproxy/haproxy.cfg

至此, 用 HAproxy 做RabbitMQ 的 LB 的集群已经配置完成, 在连接 MQ 的时候, 只要将地址配置为 haproxy-server 的 IP 和对应 Port 即可.

支付宝捐赠
请使用支付宝扫一扫进行捐赠
微信捐赠
请使用微信扫一扫进行赞赏
有 0 篇文章