我有RabbitMQ集群,其中有两个节点正在生产中,集群正在打破这些错误消息:
=错误报告==== 2011年12月23日:: 04:21:34 ===
**节点兔子@ rabbitmq02没有回复**
**删除(超时)连接**= INFO REPORT ==== 23-Dec-2011 :: 04:21:35 ===
节点兔子@ rabbitmq02失去了'兔子'=错误报告==== 2011年12月23日:: 04:21:49 ===
Mnesia(兔子@ rabbitmq01):**错误** mnesia_event得到{inconsistent_database,running_partitioned_network,rabbit @ rabbitmq02}
我试图通过使用“tcpkill”终止两个节点之间的连接来模拟问题,群集已断开连接,并且令人惊讶的是两个节点没有尝试重新连接!
当群集中断时,haproxy负载均衡器仍然将两个节点标记为活动并向两个节点发送请求,尽管它们不在群集中。
我的问题:
如果节点配置为群集,当我遇到网络故障时,他们为什么不尝试重新连接?
如何识别损坏的群集并关闭其中一个节点?分别使用两个节点时,我遇到了一致性问题。
答案 0 :(得分:13)
RabbitMQ集群在不可靠的网络上运行不佳(RabbitMQ文档的一部分)。因此,当网络故障发生时(在双节点集群中),每个节点都认为它是集群中的主节点和唯一节点。两个主节点不会自动重新连接,因为它们的状态不会自动同步(即使在RabbitMQ从站的情况下 - 实际的消息同步也不会发生 - 从站只是“赶上”消息从队列中消耗掉并且消息更多得到补充)。
要检测群集是否已损坏,请运行命令:
rabbitmqctl cluster_status
在构成群集一部分的每个节点上。如果群集中断,那么您将只看到一个节点。类似的东西:
Cluster status of node rabbit@rabbitmq1 ...
[{nodes,[{disc,[rabbit@rabbitmq1]}]},{running_nodes,[rabbit@rabbitmq1]}]
...done.
在这种情况下,您需要在构成原始群集一部分的其中一个节点上运行以下命令集(以便它作为从属连接到群集中的另一个主节点(例如rabbitmq1)) :
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbitmq1
rabbitmqctl start_app
最后再次检查群集状态..这次你应该看到两个节点。
注意:如果您使用虚拟IP在HA配置中使用RabbitMQ节点(并且客户端使用此虚拟IP连接到RabbitMQ),那么应该成为主节点的节点应该是具有虚拟IP的节点IP
答案 1 :(得分:9)
从这种故障中恢复的另一种方法是使用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(Tab,Nodes)来精确定位 节点可以加载每个表。
启动时,Mnesia的普通表加载算法将被绕过并且 该表将从为其定义的一个主节点加载 表,不管日志中潜在的mnesia_down条目。该 节点可能只包含表具有副本的节点以及它是否具有副本 是空的,特定表的主节点恢复机制 将被重置,并在下次使用正常的加载机制 重新启动。
函数mnesia:set_master_nodes(Nodes)为所有人设置主节点 表。对于每个表,它将确定其副本节点并调用 mnesia:set_master_nodes(Tab,TabNodes)与那些副本节点 包含在节点列表中(即TabNodes是 节点和表的副本节点)。如果交叉点是 清空特定表的主节点恢复机制 重置,正常加载机制将在下次重启时使用。
函数mnesia:system_info(master_node_tables)和 mnesia:table_info(Tab,master_nodes)可用于获取信息 关于潜在的主节点。
确定通信失败后要保留哪些数据 Mnesia的范围。一种方法是确定哪个“岛屿” 包含大多数节点。使用{majority,true}选项 关键表可以是确保不属于的节点的一种方法 “多数岛屿”无法更新这些表格。注意 这构成了少数民族节点服务的减少。这个 将是一种有利于更高一致性保证的权衡。
函数mnesia:force_load_table(Tab)可用于强制加载 无论激活哪种表加载机制,都可以使用该表。
这是一种从这种故障中恢复的更长时间和更复杂的方法..但会提供更好的粒度和对最终主节点中应该可用的数据的控制(这可以减少可能的数据丢失量)在“合并”RabbitMQ主人时发生。)
答案 2 :(得分:8)
RabbitMQ还提供了两种自动处理网络分区的方法:暂停 - 少数模式和自动恢复模式。 (默认行为称为忽略模式)。
在pause-minority模式下,RabbitMQ将自动暂停群集节点,这些节点在看到其他节点发生故障后确定自己处于少数(即,少于或等于节点总数的一半)。因此,它从CAP定理中选择可用性的分区容差。这确保了在网络分区的情况下,单个分区中的节点最多将继续运行。
在autoheal模式下,如果认为分区已经发生,RabbitMQ将自动决定获胜分区。它将重新启动不在获胜分区中的所有节点。获胜分区是拥有最多分区的分区 自动处理分区连接的客户端(或者如果这会产生一个绘图,那个节点数最多的那个;如果仍然产生一个绘图,那么将以未指定的方式选择其中一个分区。)
您可以通过将配置文件中Rabbit应用程序的配置参数cluster_partition_handling
设置为pause_minority
或autoheal
来启用任一模式。
我应该选择哪种模式?
了解允许RabbitMQ自动处理网络分区并不会减少问题,这一点非常重要。网络分区总是会导致RabbitMQ集群出现问题;你只是对你得到的问题有了一定程度的选择。如简介中所述,如果您想通过普遍不可靠的链接连接RabbitMQ集群,则应使用federation
plugin or the shovel
plugin。
话虽如此,您可能希望选择恢复模式,如下所示:
忽略:您的网络确实可靠。您的所有节点都在机架中,与交换机连接,该交换机也是通往外部世界的路径。如果任何其他群集发生故障(或者您有一个双节点群集),则不希望运行任何群集关闭的任何风险。
pause_minority:您的网络可能不太可靠。您已在EC2中跨3个AZ聚集,并且您假设一次只有一个AZ会失败。在那种情况下,您希望剩余的两个AZ继续工作,并且失败的AZ中的节点会自动重新加入,并且当AZ返回时不会大惊小怪。
autoheal:您的网络可能不可靠。您更关注服务的连续性而不是数据完整性。您可能有一个双节点集群。
这个答案来自rabbitmq docs。 https://www.rabbitmq.com/partitions.html会为您提供更详细的说明。