首页天道酬勤rabbitmq脱离集群,rabbitmq消费者集群

rabbitmq脱离集群,rabbitmq消费者集群

张世龙 05-12 08:02 9次浏览

首先介绍RabbitMQ集群

RabbitMQ群集有两种模式:正常模式,默认群集模式和镜像模式,可以使队列成为镜像队列

在学习两种模式之前,让我们先了解一些RabbitMQ集群的概念

元数据:包括队列元数据、交换机元数据、交换机元数据和vhost元数据

(1)队列元数据)队列名称及其属性;

)2)交换机元数据)交换机名称、类型、属性;

)3)元数据绑定:一个简单的表,显示如何将消息路由到队列

)4) vhost元数据)为vhost中的队列、交换机和绑定提供命名空间和安全属性;

由于RabbitMQ群集始终同步这四种类型的内部元数据,因此用户访问其中一个RabbitMQ节点时,在rabbitmqctl中查询的队列、交换机等信息是相同的。

节点:RabbitMQ群集包含两种类型的节点:磁盘节点和内存节点

磁盘节点:将元数据保存到硬盘。 群集中至少有一个磁盘节点,元数据至少存储在一个磁盘上。 内存节点重新启动后,将当前群集元数据复制到磁盘节点。 如果所有磁盘节点都关闭,则群集无法创建新的,但可以继续使用现有的

内存节点:内存节点的元数据存储在内存中,性能优于磁盘节点。 性能仅反映在添加和删除队列、虚拟主机和交换机等资源管理中,消息的发送和接收速度与磁盘节点相同。

RabbitMQ的两种模式

正常模式

在常规群集中,元数据信息在所有节点上是一致的,但队列的完整内容只存在于创建它的节点上,每个节点只有相同的队列元数据。 在生产者向节点a的队列发送消息之后,当消费者从节点c接收到消息时,RabbitMQ临时在节点a和c之间进行消息转发,取出节点a中的消息实体并经由节点c将其发送给消费者。

然而,这种模型存在的问题是,在节点a发生故障之后,节点c将不能获得它在节点a处未被消耗的消息实体。 如果队列不持久化,其他节点可以创建相同的队列并继续工作;但是,如果队列不持久化,如果消息不持久化,则驻留在该队列中的消息将永久丢失。 如果消息已持久化,但队列已持久化,因此其他节点无法创建相应的队列,则消息不会消耗在其他节点上,除非节点a从故障中恢复。

镜像模式

镜像模式除了通常模式之外,还将必要的队列镜像队列,并存在于多个节点上以实现高可用性(HA )。 在此模式下,镜像队列中的消息实体在镜像节点之间主动同步。 也就是说,镜像队列队列的队列内容在镜像节点之间同步,因此消费者在抽取数据时不需要临时抽取。 其中,请注意,如果队列不是镜像队列,则队列内容不会同步到每个节点。

但是,该模型除了会降低系统性能外,如果镜像队列数量过多,进入大量消息,则会消耗集群内部的大量网络带宽。 通常,对于要求可靠性的场景,建议使用镜像模式。

RabbitMQ集群搭建

我在这里构建了一个只有两台机器的RabbitMQ集群,只用作演示

1、先在两台机器上安装RabbitMQ (上一篇文章已经说过了) ) ) ) ) ) ) ) )。

2、修改两台机器的. erlang.cookie是一样的

如果我不知道你的. erlang.cookie在哪里就好了

选择a计算机上的. erlang.cookie,然后将b计算机上的. erlang.cookie更改为a计算机上的. erlang.cookie的值。 (请注意,在更改之前,请记下b机器的erlang.cookie值。 万一以后有有用的事情。 )

a机器的. erlang.cookie

b机器的. erlang.cookie

3、修改两台机器的/etc/hosts

因为RabbitMQ节点使用域名相互寻址,所以所有群集成员的主机名必须能够从所有群集节点解析。 可以修改hosts文件或使用DNS解决

添加到a和b主机

a设备公共网ip A设备名称

b设备公共网ip B设备名称

A机器

B设备

这里需要注意的是,机器名称中不能加上“.”和“-”。 用A、b机器确认可以ping两个ip后,有时会因为防火墙等问题ping不通(你是怎么知道的? 说说看! () ^ () ) )

4、完成上述步骤后,在两台机器上启动RabbitMQ,安装web管理插件

rabbitmq-server start启动RabbitMQ

rabbitmqctl start_app启动APP应用程序

rabbit MQ -插件安装程序rabbitmq _ management启用管理插件

然后,在每台计算机上运行以下命令

rabbitmqctl clu

ster_status                 查看集群状态

A机器

B机器

/*******集群中的节点,disc表示为磁盘模式,ram表示为内存模式**************/
[{nodes,[{disc,[rabbit@VM_0_15_centos]}]},

/**************正在运行的集群节点*****************/
 {running_nodes,[rabbit@VM_0_15_centos]},

/**************集群名称*********/
 {cluster_name,<<"rabbit@VM_0_15_centos">>},
 {partitions,[]},
 {alarms,[{rabbit@VM_0_15_centos,[]}]}]

其实,每一个RabbitMQ都是一个集群,只是这个集群只有一个磁盘节点Σ(⊙▽⊙"a

5、把A机器加入到B机器的集群里

在A机器上执行以下命令

rabbitmqctl stop_app           停止应用

rabbitmqctl join_cluster rabbit@VM_0_15_centos --ram              将本节点作为内存节点加入集群,不加“--ram”参数默认为磁盘节点

此时,在B机器上执行命令

rabbitmqctl cluster_status                 查看集群状态

或者登陆B机器的web管理后台

可以发现A机器已经作为内存节点加入到了集群之中,但是该节点还没有运行

在A机器上启动该节点,执行命令

rabbitmqctl start_app                      启动应用

rabbitmqctl cluster_status                 查看集群状态

可以发现该节点已被启动,此时去B机器上查看集群状态,或是去A、B的web管理后台页面均可查看集群状态,此处不再加图片说明了

此时一个普通模式的RabbitMQ集群已经搭建成功了,然后我们可以试着在A(B)机器上用命令或在web管理后台添加删除交换机,队列,虚拟主机等操作,然后在两台机器上用命令或在web管理后台中查看对应的状态,发现两者保持一致。

我们还可以试着杀掉B机器的RabbitMQ的进程,即模拟磁盘节点挂掉的情况,然后在A机器中进行添加队列等操作,正常停掉A集群的RabbitMQ,启动磁盘节点,即B机器的RabbitMQ的服务,再启动内存节点即A节点的RabbitMQ的服务,再去web管理后台或者用命令查看你刚刚添加的东西,会发现都不存在了。这是因为内存节点的元数据存在内存中,磁盘节点的元数据存放在磁盘上,磁盘节点挂掉后,内存节点新加的元数据存放在内存节点的内存中,当把内存节点停止之后,启动磁盘节点,再启动内存节点时,内存节点会从磁盘节点拉取元数据,但是磁盘节点没有这些新加的元数据,所以新加的东西就不存在了

我们还可以试试停下A机器与B机器,然后启动A机器(内存节点),会发现报错,因为内存节点启动的时候会从磁盘节点同步数据,如果磁盘节点不启动,则内存节点会一直启动失败。故关闭集群时最好最后一个关闭磁盘节点,以防止配置丢失,除此之外任何对集群的操作都要有磁盘节点在线,磁盘节点可以有多个,但是至少有一个。

图就不截了,有点多,叙述不清之处欢迎与我讨论

以下是一些集群的操作命令

从集群中删除节点

rabbitmqctl stop_app

rabbitmqctl reset                      //将节点从集群中删除,即重新配置节点的集群信息                                    

rabbitmqctl start_app

更改节点属性

rabbitmqctl stop_app  

rabbitmqctl change_cluster_node_type disc/ram          更改节点为磁盘或内存节点

rabbitmqctl start_app 

注意,在对集群节点操作的时候,第一个命令和最后一个命令一定是以下这两个命令

rabbitmqctl stop_app  

rabbitmqctl start_app 

6、镜像集群

上面已经完成RabbitMQ默认集群模式,但并不保证队列的高可用性,尽管交换机、绑定这些可以复制到集群里的任何一个节点,但是队列内容不会复制。虽然该模式解决一项目组节点压力,但队列节点宕机直接导致该队列无法应用,只能等待重启。所以要想在队列节点宕机或故障也能正常应用,就要复制队列内容到集群里的每个节点,必须要创建镜像队列。

在镜像队列模式下,如果集群中的一个节点失效了,队列能自动地切换到镜像中的另一个节点以保证服务的可用性。每一个镜像队列都包含一个master和多个slave,分别对应于不同的节点,注意一个节点既能是A队列master,又可以是B队列的slave,并非一个节点上的队列全是master。slave会准确地按照master执行命令的顺序进行命令执行,故slave与master上维护的状态应该是相同的。除了publish外所有动作都只会向master发送,然后由master将命令执行的结果广播给slave们,故看似从镜像队列中的消费操作实际上是在master上执行的。publish到镜像队列的所有消息总是被直接publish到master和所有的slave之上,这样一旦master失效了,message仍然可以继续发送到其他slave上,因此为了消息的可靠性,当master挂掉之后,最老的slave则提升为master。

镜像队列的工作原理:为队列建立一主多从,生产者发送消息时,消息会同时发送到master和所有的slave中,当消息者消费某一消息成功时,仅会通知master,然后由master通知其它的slave该消息被消费,删除该消息。但是若ack消息在消费者在发送到master后,slave收到master发送的ack消息前,master挂掉了,那么salve当选为新master时,,仍然会将该消息当做unack的消息放入队列,会造成重复消息。

那么,如何设置镜像队列呢?相信在座的各位大多都已经晓得了,对,没错,通过策略设置

我们接下来了解一些策略

设置策略的命令 rabbitmqctl set_policy [-p <vhost>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern> <definition>

p 可选参数,针对指定 vhost 下的exchange或 queue

priority 可选参数,policy 的优先级

apply-to 可选参数,策略适用的对象类型,其值可为 "queues", "exchanges" 或 "all".默认是"all"

name policy 的名称

pattern 匹配模式(正则表达式)

definition 镜像定义,json 格式,包括三部分(ha-mode,ha-params,ha-sync-mode)

ha-mode

ha-params

结果

all 所有node都要复制queue,并且当集群中添加一个新的node的时候,queue也会复制过去extactlycountqueue只会同步到ha-params中指定的count个node上,如果集群中的node个数小于count,queue将会同步到整个集群中,如果集群中的node个数大于count,当一个node包含一个mirror queue并且down的时候,一个新的mirror将会被创建nodesnodes names消息被同步到制定的节点上

以下是一些例子

所有以ha.开头的队列并镜像到集群中的所有其他队列中

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

所有以two.开头的队列并镜像到集群中任意两个node上

rabbitmqctl set_policy ha-two "^two." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'

所有以node.开头的队列并镜像到集群中指明名字的两个node上

rabbitmqctl set_policy ha-nodes "^nodes."  '{"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}

除此之外,还可以在web管理后台添加策略,符合策略匹配规则的队列会成为镜像队列,同步到其它节点(注意,镜像队列可手动同步,也可自动同步,自己可以设置)

本篇当初完成了大半,今天补了一些,所以实例较少,如有兴趣的小伙伴可以去网上搜搜更多的资料

 

 

rabbitmq镜像集群,rabbitmq消费者集群