您现在的位置是:网站首页> 编程资料编程资料

运用.net core中实例讲解RabbitMQ高可用集群构建_实用技巧_

2023-05-24 359人已围观

简介 运用.net core中实例讲解RabbitMQ高可用集群构建_实用技巧_

一、集群架构简介

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

解析说明:

最下面层是RabbitMQ的集群,没有ha镜像时是普通集群,普通集群的缺点是挂了一个机器,以这个机器为根的队列就无法使用了(一个队列的数据只会存在一个节点),无法实现高可用

所以把队列变成镜像队列,这样每个节点都会有一份完整的数据,有节点挂了也不影响使用,实现了高可用,但RabbitMQ集群本身没有实现负载均衡,也就是说对于一个三节点的集群,

每个节点的负载可能都是不相同的。

HAProxy层的作用就是为了实现RabbitMQ集群的负载均衡,但一个节点的话显然也不能高可用,所以需要两个HAProxy实现HaProxy的高可用,但没法实现自动的故障转移,就是HAProxy1挂了,

需要手动把ip地址改成HAProxy2的。

所以需要用到KeepAlived,它通常由一主一备两个节点组成,同一时间内只有主节点会提供对外服务,并同时提供一个虚拟的 IP 地址 (Virtual Internet Protocol Address ,简称 VIP),可以避免暴露真实ip 。 如果主节点故障,那么备份节点会自动接管 VIP 并成为新的主节点 ,直到原有的主节点恢复。

生产环境架构应该为:

机器1:RabbitMQ1,机器2:RabbitMQ2,机器3:RabbitMQ3,机器4:HAProxy+keeplived(主),机器5(HAProxy+keeplived(备)。

这里资源原因只有3台机器,所以搭建架构为:

172.16.2.84(rabbit1)RabbitMQ1,HAProxy+keeplived(主)
172.16.2.85(rabbit2)RabbitMQ2,HAProxy+keeplived(备)
172.16.2.86(rabbit3)RabbitMQ3

二、普通集群搭建

2.1 各个节点分别安装RabbitMQ

这里前面的章节功能使用是用的docker安装,这里集群不用docker,因为docker安装会有很多的映射,很容易扰乱,装有docker的rabbitmq的,需要先把docker停掉。

这里准备了3台机器,172.16.2.84(rabbit1),172.16.2.85(rabbit2),172.16.2.86(rabbit3),为了避免混淆,下面都会用rabbit1,rabbit2,rabbit3称呼。

rabbit1,rabbit2,rabbit3都执行一遍下面的安装。

1)安装前,先修改hostname,因为rabbitmq集群通讯需要用hostname

rabbit1机器执行

hostnamectl set-hostname rabbit1 --static

rabbit2机器执行

hostnamectl set-hostname rabbit2 --static

rabbit3机器执行

 hostnamectl set-hostname rabbit3 --static

rabbit1,rabbit2,rabbit3执行同样操作

#修改hosts,因为rabbitmq通讯要通过hostname

vi /etc/hosts

2)把ip对应hostname添加到后面

172.16.2.84 rabbit1
172.16.2.85 rabbit2
172.16.2.86 rabbit3

 # 重启网络 systemctl restart network # 重启机器 init 6

3)安装Erlang

#第一步 运行package cloud提供的erlang安装脚本
curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash

#第二步 安装erlang
yum install erlang

#第三步 查看erlang版本号,在命令行直接输入erl
erl

4)安装RabbitMQ

#第一步 先导入两个key
rpm --import https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey
rpm --import https://packagecloud.io/gpg.key

#第二步 运行package cloud提供的rabbitmq安装脚本
curl -s https://packagecloud.io/install/repositories/rabbitmq/rabbitmq-server/script.rpm.sh | sudo bash

#第三步 下载rabbit安装文件
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.9.5/rabbitmq-server-3.9.5-1.el8.noarch.rpm

#第四步
rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc

#第五步 rabbitMQ依赖
yum -y install epel-release
yum -y install socat

#第六步 安装
rpm -ivh rabbitmq-server-3.9.5-1.el8.noarch.rpm

#第七步 启用管理平台插件,启用插件后,可以可视化管理RabbitMQ
rabbitmq-plugins enable rabbitmq_management

#第八步 启动应用
systemctl start rabbitmq-server

上面rabbitmq的版本号安装文件地址:https://github.com/rabbitmq/rabbitmq-server/releases/

5)设置访问权限

 #创建管理员账户 rabbitmqctl add_user admin 123456 #设置注册的账户为管理员 rabbitmqctl set_user_tags admin administrator #授权远程访问 rabbitmqctl set_permissions -p / admin "." "." ".*" #重启服务 systemctl restart rabbitmq-server

注意这里关了防火墙,如果开启防火墙的话,需要把15672端口开放出来

 #查看防火墙状态 systemctl status firewalld #关闭防火墙 systemctl stop firewalld

到这里,3台机器都安装好了RabbitMQ。

2.2 把节点加入集群

1)停止服务rabbit2,rabbit3

 #停止全部服务 systemctl stop rabbitmq-server

2)拷贝cookie

将rabbit1上的.erlang.cookie文件拷贝到其他两台主机上。该 cookie 文件相当于密钥令牌,集群中的 RabbitMQ 节点需要通过交换密钥令牌以获得相互认证,因此处于同一集群的所有节点需要具有相同的密钥令牌,否则在搭建过程中会出现 Authentication Fail 错误,只要保证这3台机器中的.erlang.cookie内的密钥字符串一致即可,这里把rabbit1的密钥复制到rabbit2,rabbit3。

3个机器都给.erlang.cookie 400权限。

 #给600权限 chmod 600 /var/lib/rabbitmq/.erlang.cookie

rabbit1机器

#编辑文件
vi /var/lib/rabbitmq/.erlang.cookie

把内容复制出来,修改rabbit2,rabbit3这个文件的值为这个。

启动服务

 #开启全部服务 systemctl start rabbitmq-server

3)集群搭建

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

 # 1.停止服务 rabbitmqctl stop_app # 2.重置状态(需要更改节点类型的时候执行,首次不需要执行,除非你节点是以disk加入集群的) rabbitmqctl reset # 3.节点加入 #rabbitmqctl join_cluster --ram rabbit@rabbit1 rabbitmqctl join_cluster rabbit@rabbit1 # 4.启动服务 rabbitmqctl start_app

join_cluster命令有一个可选的参数 --ram,该参数代表新加入的节点是内存节点,默认是磁盘节点。如果是内存节点,则所有的队列、交换器、绑定关系、用户、访问权限和 vhost 的元数据都将存储在内存中,如果是磁盘节点,则存储在磁盘中。内存节点可以有更高的性能,但其重启后所有配置信息都会丢失,因此RabbitMQ 要求在集群中至少有一个磁盘节点,其他节点可以是内存节点,大多数情况下RabbitMQ 的性能都是够用的,可以采用默认的磁盘节点的形式。

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

操作上面的,一个普通集群就搭建成功了,打开rabbit管理界面(随便打开一个都是一样的)。

2.3 代码演示普通集群的问题

普通集群中, 第一次创建队列时,会随机选一个节点作为根节点,这个节点会存储队列的信息(交互机,路由,队列名等)和队列的数据,其它两个节点只会同步根节点的元信息(交换机,路由,队列名)等,

但不会存储队列的数据,他们是通过元信息找到根节点读写消息。

例如集群选择了rabbit2作为根节点,那么数据存储在rabbit2,rabbit1和rabbit3是没有数据的,那么如果rabbit2宕机了,队列里面的数据就取不到了。

代码演示,.NetCore5.0读取集群连接代码。

 ///  /// 获取集群连接对象 ///  ///  public static IConnection GetClusterConnection() { var factory = new ConnectionFactory { UserName = "admin",//账户 Password = "123456",//密码 VirtualHost = "/" //虚拟机 }; List list = new List() { new AmqpTcpEndpoint(){HostName="172.16.2.84",Port=5672}, new AmqpTcpEndpoint(){HostName="172.16.2.85",Port=5672}, new AmqpTcpEndpoint(){HostName="172.16.2.86",Port=5672} }; return factory.CreateConnection(list); }

生产者代码:

 ///  /// 工作队列模式 ///  public static void WorkerSendMsg() { string queueName = "worker_order";//队列名 //创建连接 using (var connection = RabbitMQHelper.GetClusterConnection()) { //创建信道 using (var channel = connection.CreateModel()) { //创建队列 channel.QueueDeclare(queueName, durable: true, exclusive: false, autoDelete: false, arguments: null); IBasicProperties properties = channel.CreateBasicProperties(); properties.Persistent = true; //消息持久化 for ( var i=0;i<10;i++) { string message = $"Hello RabbitMQ MessageHello,{i+1}"; var body = Encoding.UTF8.GetBytes(message); //发送消息到rabbitmq channel.BasicPublish(exchange: "", routingKey: queueName, mandatory: false, basicProperties: properties, body); Console.WriteLine($"发送消息到队列:{queueName},内容:{message}"); } } } }

执行:

查看RabbitMQ管理界面

RabbitMQ选择了rabbit3作为根节点,现在试一下停止rabbit3节点

 #停止服务 rabbitmqctl stop_app

发现队列不可用了,启动rabbit3,再试一下停止rabbit2

发现队列正常,试下消费数据:

 public static void WorkerConsumer() { string queueName = "worker_order"; var connection = RabbitMQHelper.GetClusterCon
                
                

-六神源码网