RabbitMQ的集群网络故障
之后没有重新连接我的RabbitMQ簇在生产两个节点和群集与这些错误消息打破:RabbitMQ的集群网络故障
=错误报告==== 23日 - 12月2011 :: 4时21分34秒===
**节点兔@ rabbitmq02没有响应**
**删除(已逾时)连接**= INFO REPORT ==== 23日 - 12月2011 :: 04 :21:35 ===
节点rabbit @ rabbitmq02丢失'rabbit'=错误报告==== 2011年12月23日:: 04:21:49 ===
Mnesia(rabbit @ rabbitmq01):**错误** mnesia_event got {inconsistent_database,running_partitioned_network,rabbit @ rabbitmq02}
我试图通过使用“tcpkill”杀死两个节点之间的连接来模拟问题,群集已断开连接,并且令人惊讶的是两个节点不尝试重新连接!
当集群中断时,haproxy负载均衡器仍将两个节点都标记为活动状态,并向两者发送请求,尽管它们不在集群中。
我的问题:
如果节点都配置为集群的工作,当我得到一个网络故障,他们为什么不尝试后重新连接?
如何识别损坏的集群并关闭其中一个节点?与两个节点分开工作时遇到一致性问题。
从这种失败中恢复的另一种方法是与Mnesia一起工作,Mnesia是RabbitMQ用作持久性机制的数据库,RabbitMQ实例(以及主/从状态)的同步由此控制。对于所有的详情,请参阅以下网址:http://www.erlang.org/doc/apps/mnesia/Mnesia_chap7.html
这里添加的相关章节:
有好几次在Mnesia可以检测网络 已经由于通信故障分区。
一个是当Mnesia已经启动并且Erlang节点再次获得 联系。然后,Mnesia将尝试联系Mnesia另一个 节点,以查看它是否也认为网络已被分割 一段时间。如果两个节点上的Mnesia已经彼此记录了mnesia_down条目 ,Mnesia会生成一个系统事件,称为 {inconsistent_database,running_partitioned_network,Node},该事件被发送给Mnesia的事件处理程序和其他可能的订阅者,其中 。 默认事件处理程序向错误记录器报告错误。
Mnesia可能会检测到由于通信故障而分割了网络的另一种情况是启动时。如果Mnesia 检测到本地节点和另一个节点从彼此接收到mnesia_down ,则它生成{inconsistent_database, starting_partitioned_network,Node}系统事件并且如上所述的 那样起作用。
如果应用程序检测到已经存在通信故障 ,其可能造成不一致的数据库,它可以使用 函数mnesia:set_master_nodes(制表,节点),从该 节点每个表可以被加载到精确定位。
在启动时,无论mnesia中潜在的mnesia_down条目如何,Mnesia的正常表加载算法都将被绕过,并且将从表中定义的其中一个主节点加载该表。 节点可能只包含表中有复制副本的节点,并且如果节点为空,则将重置特定表 的主节点恢复机制,并在下一个 重新启动时使用正常加载机制。
函数mnesia:set_master_nodes(Nodes)为所有 表设置主节点。对于每个表,它将确定其副本节点,并调用具有 包括在节点列表中的那些副本节点(即,TabNodes是该表的副本节点和 节点的交集)的mnesia:set_master_nodes(Tab,TabNodes)。如果交叉点为空,则对特定表的主节点恢复机制将被重置,并且在下次重新启动时将使用正常加载机制。
函数mnesia:system_info(master_node_tables)和 mnesia:table_info(Tab,master_nodes)可用于获取有关潜在主节点的信息 。
确定通信失败后要保留的数据是否在 Mnesia的范围之外。一种方法是确定哪个“岛”包含大部分节点。使用 关键表的{majority,true}选项可以确保不属于“多数岛”的部分 的节点不能更新这些表。请注意0这构成了少数节点服务的减少。这个 将是一个有利于更高一致性保证的折衷。
无论哪个表加载机制被激活,函数mnesia:force_load_table(Tab)都可以用来强制加载表 表。
这是从这样的故障中恢复的一个更费时又复杂的方式..但会提供更好的粒度和通过数据控制应该是在最终的主节点可用的(这可以减少数据丢失的量可能发生在“合并”RabbitMQ大师时)。
RabbitMQ集群在不可靠的网络(RabbitMQ文档的一部分)上无法正常工作。因此,当网络故障发生时(在两节点群集中),每个节点都认为它是群集中的主节点和唯一节点。两个主节点不会自动重新连接,因为它们的状态不会自动同步(即使是在RabbitMQ从站的情况下 - 实际的消息同步也不会发生 - 当从消息队列中消耗消息时,从站只会“追上来”得到补充)。
要检测是否有一个破碎簇,运行下面的命令:
rabbitmqctl cluster_status
在每个形成该集群的节点。如果集群已损坏,则只能看到一个节点。喜欢的东西:
Cluster status of node [email protected] ...
[{nodes,[{disc,[[email protected]]}]},{running_nodes,[[email protected]]}]
...done.
在这种情况下,你需要在所形成的原始簇的一部分(以便加入其他主节点(说rabbitmq1)的一个节点上运行以下命令集在群集中作为奴隶):
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster [email protected]
rabbitmqctl start_app
最后再次检查群集状态..这次你应该看到两个节点。
注意:如果您在使用虚拟IP的HA配置中使用RabbitMQ节点(并且客户端使用此虚拟IP连接到RabbitMQ),那么应该成为主节点的节点应该是具有虚拟IP。
RabbitMQ还提供了两种自动处理网络分区的方式:暂停少数模式和自动模式。 (默认行为被称为忽略模式)。
暂停少数模式RabbitMQ会在看到其他节点关闭后自动暂停确定自己处于少数(即少于或等于节点总数一半)的群集节点。因此,它从CAP定理中选择对可用性的分区容差。这确保了在网络分区的情况下,单个分区中的节点至多将继续运行。
在自动模式下,如果分区被视为已经发生,RabbitMQ将自动决定获胜的分区。它将重新启动不在获胜分区中的所有节点。获胜的分区是其具有最 自动处理分区
客户端连接(或者如果这产生平局,具有最节点之一;以及如果仍可产生平局,则分区中的一个是以未指定的方式选择)。
您可以通过将配置文件中的兔子应用程序的配置参数cluster_partition_handling设置为pause_minority或autoheal来启用任一模式。
我应该选择哪种模式?
理解允许RabbitMQ自动处理网络分区并不能减少问题是很重要的。网络分区总是会给RabbitMQ集群带来问题;你只是在某种程度上选择了你遇到的问题。如前言所述,如果您想通过通常不可靠的链接连接RabbitMQ群集,则应使用联合身份验证或铲。
虽这么说,你不妨选择一个恢复模式如下:
忽略 您的网络真的是可靠的。你所有的节点都在一个机架上,与交换机相连,而且这个交换机也是通向外部世界的路由。如果任何其他部分失败(或者您有两个节点群集),则不希望发生任何群集关闭的风险。
pause_minority 您的网络可能不太可靠。你在EC2中聚集了3个AZ,并且你认为只有一个AZ会一次失败。在这种情况下,您希望剩余的两个AZ继续工作,并且失败的AZ中的节点可以在AZ返回时自动重新加入,而不会大惊小怪。
autoheal 您的网络可能不够稳定。与数据完整性相比,您更关心服务的连续性。您可能有两个节点群集。
此答案来自rabbitmq文档。 https://www.rabbitmq.com/partitions.html会给你更详细的描述。
是否可以将节点配置为DO,只要网络再次可用,就自动同步它们的状态? – 2013-04-08 08:20:51
不是我所知(除非在更新版本的RabbitMQ中可用...我至少还没有检查过一年)。 – 2013-09-11 03:35:26