RabbitMQ 高可用集群搭建

RabbitMQ 高可用集群搭建

1 集群简介

1.1 集群架构

​ 当单台 RabbitMQ 服务器的处理消息的能力达到瓶颈时,此时可以通过 RabbitMQ 集群来进行扩展,从而达到提升吞吐量的目的。RabbitMQ 集群是一个或多个节点的逻辑分组,集群中的每个节点都是对等的,每个节点共享所有的用户,虚拟主机,队列,交换器,绑定关系,运行时参数和其他分布式状态等信息。一个高可用,负载均衡的 RabbitMQ 集群架构应类似下图:

img

这里对上面的集群架构做一下解释说明:

​ 首先一个基本的 RabbitMQ 集群不是高可用的,虽然集群共享队列,但在默认情况下,消息只会被路由到某一个节点的符合条件的队列上,并不会同步到其他节点的相同队列上。假设消息路由到 node1 的 my-queue 队列上,但是 node1 突然宕机了,那么消息就会丢失,想要解决这个问题,需要开启队列镜像,将集群中的队列彼此之间进行镜像,此时消息就会被拷贝到处于同一个镜像分组中的所有队列上。

​ 其次 RabbitMQ 集群本身并没有提供负载均衡的功能,也就是说对于一个三节点的集群,每个节点的负载可能都是不相同的,想要解决这个问题可以通过硬件负载均衡或者软件负载均衡的方式,这里我们选择使用 HAProxy 来进行负载均衡,当然也可以使用其他负载均衡中间件,如LVS等。HAProxy 同时支持四层和七层负载均衡,并基于单一进程的事件驱动模型,因此它可以支持非常高的井发连接数。

接着假设我们只采用一台 HAProxy ,那么它就存在明显的单点故障的问题,所以至少需要两台 HAProxy ,同时这两台 HAProxy 之间需要能够自动进行故障转移,通常的解决方案就是 KeepAlivedKeepAlived 采用 VRRP (Virtual Router Redundancy Protocol,虚拟路由冗余协议) 来解决单点失效的问题,它通常由一组一备两个节点组成,同一时间内只有主节点会提供对外服务,并同时提供一个虚拟的 IP 地址 (Virtual Internet Protocol Address ,简称 VIP) 。 如果主节点故障,那么备份节点会自动接管 VIP 并成为新的主节点 ,直到原有的主节点恢复。

最后,任何想要连接到 RabbitMQ 集群的客户端只需要连接到虚拟 IP,而不必关心集群是何种架构,示例如下:

ConnectionFactory factory = new ConnectionFactory();
// 假设虚拟ip为 192.168.0.200
factory.setHost("192.168.0.200");

1.2 部署情况

下面我们开始进行搭建,这里我使用三台主机,主机名分别为 rabbit-node2, rabbit-node3 和 rabbit3 ,其功能分配如下:

主机名 IP地址 部署服务 操作系统 配置
rabbit-node1 192.168.0.12 RabbitMQ + HAProxy + KeepAlived CentOS 7.6 4核8G
rabbit-node2 192.168.0.14 RabbitMQ + HAProxy + KeepAlived CentOS 7.6 4核8G
rabbit-node3 192.168.0.15 RabbitMQ CentOS 7.6 4核8G

以上三台主机上我均已安装好了 RabbitMQ ,关于 RabbitMQ 的安装步骤可以参考:《RabbitMQ单机环境搭建》

2 RabbitMQ 集群搭建

2.1 初始化环境

分别修改主机名

hostnamectl set-hostname rabbit-node1

修改每台机器的 /etc/hosts 文件

cat >> /etc/hosts <<EOF
192.168.0.12 rabbit-node1
192.168.0.14 rabbit-node2
192.168.0.15 rabbit-node3
EOF

重启虚拟机便于系统识别hosts

# 重启网络
systemctl restart network
setenforce 0
# 重启
init 6

2.2 配置 Erlang Cookie

将 rabbit-node1 上的 .erlang.cookie 文件拷贝到其他两台主机上。该 cookie 文件相当于密钥令牌,集群中的 RabbitMQ 节点需要通过交换密钥令牌以获得相互认证,因此处于同一集群的所有节点需要具有相同的密钥令牌,否则在搭建过程中会出现 Authentication Fail 错误。

RabbitMQ 服务启动时,erlang VM 会自动创建该 cookie 文件,默认的存储路径为 /var/lib/rabbitmq/.erlang.cookie$HOME/.erlang.cookie,该文件是一个隐藏文件,需要使用 ls -al 命令查看。(拷贝.cookie时,各节点都必须停止MQ服务):

# 停止所有服务,构建Erlang的集群环境
systemctl stop rabbitmq-server
scp /var/lib/rabbitmq/.erlang.cookie root@rabbit-node2:/var/lib/rabbitmq/
scp /var/lib/rabbitmq/.erlang.cookie root@rabbit-node3:/var/lib/rabbitmq/

由于你可能在三台主机上使用不同的账户进行操作,为避免后面出现权限不足的问题,这里建议将 cookie 文件原来的 400 权限改为 600,命令如下:

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

注:cookie 中的内容就是一行随机字符串,可以使用 cat 命令查看。

2.3 启动服务

在三台主机上均执行以下命令,启动 RabbitMQ 服务:

systemctl start rabbitmq-server

开通 EPMD 端口

epmd进程使用的端口。用于RabbitMQ节点和CLI工具的端点发现服务。

# 开启防火墙 4369 端口
firewall-cmd --zone=public --add-port=4369/tcp --permanent
# 重启
systemctl restart firewalld.service

2.4 集群搭建

RabbitMQ 集群的搭建需要选择其中任意一个节点为基准,将其它节点逐步加入。这里我们以 rabbit-node1 为基准节点,将 rabbit-node2 和 rabbit-node3 加入集群。在 rabbit-node2 和rabbit-node3 上执行以下命令:

# 1.停止服务
rabbitmqctl stop_app
# 2.重置状态
rabbitmqctl reset
# 3.节点加入, 在一个node加入cluster之前,必须先停止该node的rabbitmq应用,即先执行stop_app
# rabbit-node2加入node1, rabbit-node3加入node2
rabbitmqctl join_cluster rabbit@rabbit-node1
# 4.启动服务
rabbitmqctl start_app

join_cluster 命令有一个可选的参数 --ram ,该参数代表新加入的节点是内存节点,默认是磁盘节点。如果是内存节点,则所有的队列、交换器、绑定关系、用户、访问权限和 vhost 的元数据都将存储在内存中,如果是磁盘节点,则存储在磁盘中。内存节点可以有更高的性能,但其重启后所有配置信息都会丢失,因此RabbitMQ 要求在集群中至少有一个磁盘节点,其他节点可以是内存节点。当内存节点离开集群时,它可以将变更通知到至少一个磁盘节点;然后在其重启时,再连接到磁盘节点上获取元数据信息。除非是将 RabbitMQ 用于 RPC 这种需要超低延迟的场景,否则在大多数情况下,RabbitMQ 的性能都是够用的,可以采用默认的磁盘节点的形式。这里为了演示, rabbit-node3 我就设置为内存节点。

另外,如果节点以磁盘节点的形式加入,则需要先使用 reset 命令进行重置,然后才能加入现有群集,重置节点会删除该节点上存在的所有的历史资源和数据。采用内存节点的形式加入时可以略过 reset 这一步,因为内存上的数据本身就不是持久化的。

2.5 查看集群状态

2.5.1 命令行查看

在 rabbit-node3 和 3 上执行以上命令后,集群就已经搭建成功,此时可以在任意节点上使用 rabbitmqctl cluster_status 命令查看集群状态,输出如下:

[root@rabbit-node1 keepalived]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit-node1 ...
[{
   nodes,[
  • 53
    点赞
  • 326
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
RabbitMQ本身并不直接支持分布式事务,但是可以通过一些机制来实现分布式事务。 一种常用的方式是使用两阶段提交(Two-Phase Commit,简称2PC)协议来实现分布式事务。在这种方案中,事务的协调者(coordinator)会与多个参与者(participants)进行通信,以确保所有参与者在提交或者回滚事务时的一致性。 在RabbitMQ中,可以将消息生产者作为事务的协调者,将消息消费者作为参与者。下面是一个简单的示例: 1. 生产者发送消息到RabbitMQ,并开启一个事务。 2. 生产者将消息发送给消费者,并等待消费者返回确认消息。 3. 如果所有的消费者都成功处理了消息,则协调者发送“prepare”消息给所有的参与者。 4. 参与者收到“prepare”消息后,将消息持久化到本地存储,并发送“ready”消息给协调者。 5. 协调者收到所有参与者的“ready”消息后,发送“commit”消息给所有的参与者。 6. 参与者收到“commit”消息后,正式提交事务,并发送确认消息给协调者。 7. 协调者收到所有参与者的确认消息后,完成事务。 需要注意的是,如果任何一个参与者在处理消息时出现异常,协调者将发送“rollback”消息,参与者接收到“rollback”消息后会回滚事务。 这只是一个简单的示例,实际的实现可能需要考虑更多的细节和异常处理。另外,还有其他的分布式事务解决方案,如Saga模式、TCC(Try-Confirm-Cancel)模式等,也可以根据具体需求选择合适的方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值