RabbitMQ高可用

您所在的位置:网站首页 rabbitmq队列模式 RabbitMQ高可用

RabbitMQ高可用

#RabbitMQ高可用| 来源: 网络整理| 查看: 265

RabbitMQ高可用-镜像模式部署使用

目录RabbitMQ高可用-镜像模式部署使用一、概述二、配置普通集群模式三、配置镜像集群模式3.1.通过命令行配置3.2.通过管理界面配置四、配置高可用五、集群常用命令六、rabbitmq中镜像队列注意点七、rabbitmq中镜像队列的故障恢复八、更多参考资料

一、概述 RabbitMQ的Cluster集群模式一般分为两种,普通模式和镜像模式。消息队列通过rabbitmq HA镜像队列进行消息队列实体复制。 RabbitMQ集群普通模式考虑到性能和存储空间,仅采用元数据同步的方式。即其他节点不会实际存储消息数据。 生产者和消费者连接在哪个节点上,则消息就存储在哪个节点上,其他节点仅会存储元数据,如果消费者获取的数据不在当前节点上,则内部会路由到实际存储消息的节点上。 我们在实际集群部署时,考虑到高可用性,一般都会使用镜像模式。 在RabbitMQ集群中的节点只有两种类型:内存节点/磁盘节点,单节点系统只运行磁盘类型的节点。而在集群中,可以选择配置部分节点为内存节点。内存节点,就是将元数据(metadata)都放在内存里,磁盘节点就是放在磁盘上。如果RabbitMQ是单节点运行,默认就是磁盘节点。在RabbitMQ集群里,至少有一个磁盘节点,它用来持久保存元数据。新的节点加入集群后,会从磁盘节点上拷贝数据。但是,集群里也不必要每个节点都是磁盘节点,这主要是性能问题。例如,压力大的RPC服务,每秒都要创建和销毁数百个队列,如果集群里都是磁盘节点,意味着队列定义在每个节点上,都要写入磁盘才算成功,这样就会非常慢。 如果集群里只有一个磁盘节点,这个节点挂了,会发生什么?此时消息路由机制仍可正常进行(可以正常投递和消费消息),但是不能做如下事:create queues,create exchanges,create bindings,add users,change permissions,add or remove cluster nodes 所以,考虑到高可用性,推荐在集群里保持2个磁盘节点,这样一个挂了,另一个还可正常工作。但上述最后一点,往集群里增加或删除节点,要求2个磁盘节点同时在线。 如果2个节点,则建议都设为磁盘节点,如果3个节点,则可2个磁盘节点+1个内存节点。 RabbitMQ安装可参考上一篇博文:https://www.cnblogs.com/huligong1234/p/13548573.html 部署方案: CentOS7.8 x64 mq01:192.168.100 mq02:192.168.101 二、配置普通集群模式 把mq01的cookie值复制到mq02服务器 配置cookie vi /var/lib/rabbitmq/.erlang.cookie 确保rabbitMQ服务处于停止状态:service rabbitmq-server stop 确保2个节点的coolie文件使用相同的值 cookie文件默认路径为/var/lib/rabbitmq/.erlang.cookie(RPM安装) 或者$home/.erlang.cookie(解压方式安装) .erlang.cookie设置可写 chmod u+w /var/lib/rabbitmq/.erlang.cookie 加入集群(默认加入的为磁盘节点) rabbitmqctl join_cluster rabbit@mq02 如果要使用内存节点,则可以使用 rabbitmqctl join_cluster --ram rabbit@mq02 查看集群状态 rabbitmqctl cluster_status 三、配置镜像集群模式 3.1.通过命令行配置 rabbitmqctl set_policy [ha-all] "^" '{"ha-mode":"all"}' //策略正则表达式为 “^” 表示所有匹配所有队列名称 rabbitmqctl set_policy -p [虚拟主机名称] [策略名称如ha-all ] "^" '{"ha-mode":"all" , "ha-sync-mode":"automatic"}' 在任意一个节点上执行: rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all" , "ha-sync-mode":"automatic"}' 或者指定vhost: rabbitmqctl set_policy -p demo ha-all "^" '{"ha-mode":"all" , "ha-sync-mode":"automatic"}' 将所有队列设置为镜像队列,即队列会被复制到各个节点,各个节点状态保持一直。 到这里,RabbitMQ 高可用集群就已经搭建好了,最后一个步骤就是搭建均衡器。 策略名称:自定义 “^”:匹配所有队列 ha-sync-mode: 默认为手动,可以配置为自动,区别在于,如果是自动做镜像回复,则该队列会处于不可用状态直到同步完成 3.2.通过管理界面配置

界面配置示例(http://ip:15672/):

配置完后:

四、配置高可用

可以采用HAProxy+Keepalived 或 Nginx+Keepalived方式来部署实现。

我这里根据实际使用场采用另一种简洁方案,如下图所示,仅使用Nginx,配置backup路由策略,减轻部署复杂性。

五、集群常用命令 1、加入集群[--ram添加内存模式 默认disk模式] rabbitmqctl join_cluster --ram rabbit@mq01 2、查看集群状态 rabbitmqctl cluster_status 3、更改节点模式[顺序 关闭运用-〉更改类型->开启运用] rabbitmqctl stop_app –停止运用服务 rabbitmqctl change_cluster_node_type disc/ram –更改节点为磁盘或内存节点 rabbitmqctl start_app –开启运用服务 4、创建策略(集群同步策略……) set_policy [-p vhostpath] {name} {pattern} {definition} [priority] 5、查看策略 rabbitmqctl list_policies 6、移除远程offline的节点 1.节点2停掉应用 rabbitmqctl stop_app 2.节点1执行删除 rabbitmqctl forget_cluster_node rabbit@mq02 7、设置集群名称 rabbitmqctl set_cluster_name cluster_name 8、设置镜像模式 Rabbit提供镜像功能,需要基于rabbitmq策略来实现,政策是用来控制和修改群集范围的某个vhost队列行为和Exchange行为 set_policy [-p vhostpath] {name} {pattern} {definition} [priority] rabbitmqctl set_policy ha-all "^ha." "{""ha-mode"":""all""}" rabbitmqctl set_policy ha-all "^" "{""ha-mode"":""all"",""ha-sync-mode"":""automatic""}" rabbitmqctl set_policy -p demo ha-all "^" "{""ha-mode"":""all"",""ha-sync-mode"":""automatic""}" 9、手动同步queue rabbitmqctl sync_queue name 10、取消queue同步 rabbitmqctl cancel_sync_queue name 11、查看所有队列信息 rabbitmqctl list_queues 12、获取队列信息 rabbitmqctl list_queues[-p vhostpath] [queueinfoitem ...] Queueinfoitem可以为:name,durable,auto_delete,arguments,messages_ready,messages_unacknowledged,messages,consumers,memory。 13、获取Exchange信息 rabbitmqctl list_exchanges[-p vhostpath] [exchangeinfoitem ...] Exchangeinfoitem有:name,type,durable,auto_delete,internal,arguments。 14、获取Binding信息 rabbitmqctl list_bindings[-p vhostpath] [bindinginfoitem ...] Bindinginfoitem有:source_name,source_kind,destination_name,destination_kind,routing_key,arguments。 15、获取Connection信息 rabbitmqctl list_connections [connectioninfoitem ...] Connectioninfoitem有:recv_oct,recv_cnt,send_oct,send_cnt,send_pend等。 16、获取Channel信息 rabbitmqctl list_channels[channelinfoitem ...] Channelinfoitem有consumer_count,messages_unacknowledged,messages_uncommitted,acks_uncommitted,messages_unconfirmed,prefetch_count,client_flow_blocked。 六、rabbitmq中镜像队列注意点

RabbitMQ的mirror queue(镜像队列)机制是最简单的队列HA方案,它通过在cluster的基础上增加ha-mode、ha-param等policy选项,可以根据需求将cluster中的队列镜像到多个节点上,从而实现高可用,消除cluster模式中队列内容单点带来的风险。

在使用镜像队列之前,有几点注意事项: 1.镜像队列不能作为负载均衡使用,因为每个操作在所有节点都要做一遍。 2.ha-mode参数和durable declare对exclusive队列都不生效,因为exclusive队列是连接独占的,当连接断开,队列自动删除。所以实际上这两个参数对exclusive队列没有意义。 3.将新节点加入已存在的镜像队列时,默认情况下ha-sync-mode=manual,镜像队列中的消息不会主动同步到新节点,除非显式调用同步命令。当调用同步命令(via rabbitmqctl or web-based ui)后,队列开始阻塞,无法对其进行操作,直到同步完毕。当ha-sync-mode=automatic时,新加入节点时会默认同步已知的镜像队列。由于同步过程的限制,所以不建议在生产环境的active队列(有生产消费消息)中操作。 4.每当一个节点加入或者重新加入(例如从网络分区中恢复回来)镜像队列,之前保存的队列内容会被清空。 5.镜像队列有主从之分,一个主节点(master),0个或多个从节点(slave)。当master宕掉后,会在slave中选举新的master。选举算法为最早启动的节点。 6.当所有slave都处在(与master)未同步状态时,并且ha-promote-on-shutdown policy设置为when-syned(默认)时,如果master因为主动的原因停掉,比如是通过rabbitmqctl stop命令停止或者优雅关闭OS,那么slave不会接管master,也就是说此时镜像队列不可用;但是如果master因为被动原因停掉,比如VM或者OS crash了,那么slave会接管master。这个配置项隐含的价值取向是优先保证消息可靠不丢失,放弃可用性。如果ha-promote-on-shutdown policy设置为alway,那么不论master因为何种原因停止,slave都会接管master,优先保证可用性。 7.镜像队列中最后一个停止的节点会是master,启动顺序必须是master先起,如果slave先起,它会有30秒的等待时间,等待master启动,然后加入cluster。当所有节点因故(断电等)同时离线时,每个节点都认为自己不是最后一个停止的节点。要恢复镜像队列,可以尝试在30秒之内同时启动所有节点。 8.对于镜像队列,客户端basic.publish操作会同步到所有节点;而其他操作则是通过master中转,再由master将操作作用于salve。比如一个basic.get操作,假如客户端与slave建立了TCP连接,首先是slave将basic.get请求发送至master,由master备好数据,返回至slave,投递给消费者。 9.由8可知,当slave宕掉时,除了与slave相连的客户端连接全部断开之外,没有其他影响。当master宕掉时,会有以下连锁反应: 1)与master相连的客户端连接全部断开。 2)选举最老的slave为master。若此时所有slave处于未同步状态,则未同步部分消息丢失。 3)新的master节点requeue所有unack消息,因为这个新节点无法区分这些unack消息是否已经到达客户端,亦或是ack消息丢失在到老master的通路上,亦或是丢在老master组播ack消息到所有slave的通路上。所以处于消息可靠性的考虑,requeue所有unack的消息。此时客户端可能受到重复消息。 4)如果客户端连着slave,并且basic.consume消息时指定了x-cancel-on-ha-failover参数,那么客户端会收到一个Consumer Cancellation Notification通知,Java SDK中会回调Consumer接口的handleCancel()方法,故需覆盖此方法。如果不指定x-cancel-on-ha-failover参数,那么消费者就无法感知master宕机,会一直等待下去。 上面列出的注意事项整理自官方的HA文档。

七、rabbitmq中镜像队列的故障恢复

前提:两个节点(A和B)组成一个镜像队列。

1.场景1:A先停,B后停。 该场景下B是master(disk,A是ram),只要先启动B,再启动A即可。或者先启动A,再在30秒之内启动B即可恢复镜像队列。 2.场景2: A, B同时停。 该场景可能是由掉电等原因造成,只需在30秒之内连续启动A和B即可恢复镜像队列。 3.场景3:A先停,B后停,且A无法恢复。 该场景是场景1的加强版,因为B是master,所以等B起来后,在B节点上调用rabbitmqctl forget_cluster_node A,解除与A的cluster关系,再将新的slave节点加入B即可重新恢复镜像队列。 4.场景4:A先停,B后停,且B无法恢复。 该场景是场景3的加强版,比较难处理,早在3.1.x时代之前貌似都没什么好的解决方法,但是现在已经有解决方法了,在3.4.2版本亲测有效(我们当前使用的是3.3.5)。因为B是master,所以直接启动A是不行的,当A无法启动时,也就没办法在A节点上调用rabbitmqctl forget_cluster_node B了。新版本中,forget_cluster_node支持–offline参数,offline参数允许rabbitmqctl在离线节点上执行forget_cluster_node命令,迫使RabbitMQ在未启动的slave节点中选择一个作为master。当在A节点执行rabbitmqctl forget_cluster_node –offline B时,RabbitMQ会mock一个节点代表A,执行forget_cluster_node命令将B剔出cluster,然后A就能正常启动了。最后将新的slave节点加入A即可重新恢复镜像队列。 5.场景5: A先停,B后停,且A、B均无法恢复,但是能得到A或B的磁盘文件。 该场景是场景4的加强版,更加难处理。将A或B的数据库文件(默认在$RABBIT_HOME/var/lib目录中)拷贝至新节点C的目录下,再将C的hostname改成A或B的hostname。如果拷过来的是A节点磁盘文件,按场景4处理方式;如果拷过来的是B节点磁盘文件,按场景3处理方式。最后将新的slave节点加入C即可重新恢复镜像队列。 6.场景6:A先停,B后停,且A、B均无法恢复,且无法得到A或B的磁盘文件。 洗洗睡吧,该场景下已无法恢复A、B队列中的内容了。

八、更多参考资料 RabbitMQ集群原理介绍 rabbitmq高可用-镜像队列模式 RabbitMQ集群架构模式 RabbitMQ 3.7.X集群:从入门到精通,这一篇就够了 缓存架构之史上讲的最明白的RabbitMQ可靠消息传输实战演练 Rabbitmq集群高可用部署详细 Rabbitmq 相关介绍之单机镜像模式集群配置 亲测可用,超详细RabbitMQ消息队列集群配置 消息中间件—RabbitMQ(集群原理与搭建篇) RabbitMQ系列(六)你不知道的RabbitMQ集群架构全解 RabbitMQ 高可用集群搭建及电商平台使用经验总结 rabbitmq集群镜像模式使用中的一些坑 RabbitMQ手册之rabbitmqctl


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3