Кластер RabbitMQ не восстанавливается после сбоя сети

У меня есть кластер RabbitMQ с двумя узлами в производстве, и кластер ломается с этими сообщениями об ошибках:

=отчет об ошибке= = = = 23-Dec-2011::04:21:34 ===
** Узел rabbit@rabbitmq02 не отвечает **
** Удаление (тайм-аут) соединения **

=информационный отчет= = = = 23-Dec-2011::04:21:35 ===
узел кролик@rabbitmq02 потерял "кролик"

=отчет об ошибке= = = = 23-Dec-2011::04:21:49 ===
Mnesia (rabbit@rabbitmq01): * * ошибка * * mnesia_event получил {inconsistent_database, running_partitioned_network, rabbit@rabbitmq02}

Я попытался смоделировать проблему, убив соединение между двумя узлами с помощью "tcpkill", кластер отключился, и удивительно, что два узла не пытаются повторно подключиться !

когда кластер ломается, балансировщик нагрузки haproxy по-прежнему помечает оба узла как активные и отправляет запрос на оба из них, хотя они не находятся в группа.

мои вопросы:

  1. Если узлы настроены на работу в качестве кластера, когда я получаю сбой в Сети , Почему они не пытаются восстановить после ?

  2. Как я могу определить сломанный кластер и выключить один из узлов ? У меня проблемы с согласованностью при работе с двумя узлами отдельно.

3 ответов


еще один способ восстановления после такого сбоя-работа с Mnesia, которая является базой данных, которую RabbitMQ использует в качестве механизма сохранения, и для синхронизации экземпляров RabbitMQ (и состояния master / slave) управляются этим. Для всех деталей, см. следующий URL:http://www.erlang.org/doc/apps/mnesia/Mnesia_chap7.html

добавление соответствующего раздела здесь:

есть несколько случаев, когда Mnesia может обнаружить, что сеть был разделен из-за сбоя связи.

когда Mnesia уже запущен и Эрланга узлов усиления снова контакт. Затем Mnesia постараемся связаться с Mnesia на других узел, чтобы увидеть, если он также думает, что сеть была перегорожена на некоторое время. Если Mnesia на обоих узлах зарегистрировала записи mnesia_down друг от друга, Mnesia генерирует системное событие, называется {inconsistent_database, running_partitioned_network, узел}, который отправлено обработчику событий Mnesia и другим возможным подписчикам. Этот обработчик событий по умолчанию сообщение об ошибке в журнал ошибок.

еще один случай, когда Mnesia может обнаружить, что сеть была секционированный из-за сбоя связи, находится при запуске. Если Мнезия обнаруживает, что и локальный узел, и другой узел получили mnesia_down друг от друга он генерирует {inconsistent_database, starting_partitioned_network, Node} системное событие и действует так, как описано выше.

Если приложение обнаруживает, что произошел сбой связи что может привести к несогласованности базы данных, она может использовать функция mnesia: set_master_nodes (вкладка, узлы), чтобы точно указать, из которого узлы каждая таблица может быть загружена.

при запуске нормальный алгоритм загрузки таблицы Mnesia будет обойден и таблица будет загружена с одного из главных узлов, определенных для таблица, независимо от потенциальные записи mnesia_down в журнале. Этот Узлы могут содержать только узлы, где таблица имеет реплику и если она является пустым, механизм восстановления главного узла для конкретной таблицы будет переустановлен и нормальный механизм нагрузки будет использован когда следующий перезапуск.

функция mnesia: set_master_nodes (Nodes) устанавливает главные узлы для всех таблицы. Для каждой таблицы он определит свои узлы реплики и вызовет mnesia: set_master_nodes (Tab, TabNodes) с этими репликами узлы включены в список узлов (т. е. Табноды-это пересечение Узлы и реплики узлов таблицы). Если пересечение очистите механизм восстановления главного узла для конкретной таблицы сброс и нормальный механизм загрузки будет использоваться при следующем перезапуске.

функции mnesia:system_info(master_node_tables) и mnesia:table_info (Tab, master_nodes) может использоваться для получения информации о потенциальных главных узлах.

определение того, какие данные хранить после сбоя связи снаружи объем Mnesia. Один из подходов заключается в определении того, какой " остров" содержит большинство узлов. Использование параметра {majority, true} для критические таблицы могут быть способом обеспечения того, чтобы узлы, которые не являются частью "остров большинства" не в состоянии обновить эти таблицы. Заметить что это представляет собой сокращение обслуживания на узлах меньшинства. Этот было бы компромиссом в пользу более высокой последовательности гарантированное обеспечение.

функция mnesia:force_load_table (Tab) может использоваться для принудительной нагрузки таблица независимо от того, какой механизм нагрузки таблицы активирован.

это более длительный и сложный способ восстановления после таких сбоев .. но даст лучшую гранулярность и контроль над данными, которые должны быть доступны в конечном главном узле (это может уменьшить количество потерь данных, которые могут произойти при "слиянии" мастеров RabbitMQ).


кластеры 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

наконец, проверьте состояние кластера еще раз .. на этот раз вы должны увидеть оба узла.

Примечание: Если у вас есть узлы RabbitMQ в конфигурации HA с использованием виртуального IP (и клиенты подключаются к RabbitMQ с помощью этого виртуального IP), то узел, который должен быть сделан мастером, должен быть тем, который имеет виртуальный IP.


RabbitMQ также предлагает два способа автоматической работы с сетевыми разделами: режим паузы-меньшинства и режим автоподогрева. (Поведение по умолчанию называется режимом игнорирования).

в режиме паузы-меньшинства RabbitMQ автоматически приостанавливает узлы кластера, которые определяют себя как находящиеся в меньшинстве (т. е. меньше или равны половине общего числа узлов) после просмотра других узлов. Поэтому он выбирает допуск разбиения над доступностью из теоремы CAP. Этот гарантирует, что в случае сетевого раздела, не более узлов в одном разделе будет продолжать работать.

в режиме autoheal RabbitMQ автоматически примет решение о выигрышном разделе, Если раздел считается произошедшим. Он перезапустит все узлы, которые не находятся в выигрышном разделе. Выигрышный раздел-это тот, который имеет больше всего автоматическая обработка разделов подключенные клиенты (или, если это создает ничью, с наибольшим количеством узлов; и если это все еще создает ничью, то один из разделов выбирается неопределенным способом).

вы можете включить режим, установив параметр конфигурации cluster_partition_handling для приложения rabbit в вашем файле конфигурации либо pause_minority или autoheal.

какой режим я должен выбрать?

важно понимать, что разрешение RabbitMQ автоматически работать с сетевыми разделами не делает их менее проблемными. Сеть разделы всегда будут вызывать проблемы для кластеров RabbitMQ; вы просто получаете некоторую степень выбора над тем, какие проблемы вы получаете. Как указано во введении, если вы хотите подключить кластеры RabbitMQ по ненадежным ссылкам, вы должны использовать federation плагин или shovel плагин.

С учетом сказанного, вы можете выбрать режим восстановления следующим образом:

  • игнорировать: сеть очень надежна. Все ваши узлы находятся в стойке, соединенной с коммутатором, и этот коммутатор также является маршрутом во внешний мир. Вы не хотите рисковать завершением работы кластера, если какая-либо другая его часть завершится неудачно (или у вас есть кластер из двух узлов).

  • pause_minority: ваша сеть, возможно, менее надежна. Вы сгруппировались через 3 AZs в EC2, и вы предполагаете, что только один AZ потерпит неудачу сразу. В этом случае вы хотите, чтобы оставшиеся два AZs продолжались работа и узлы от неудачного AZ воссоединиться автоматически и без суеты, когда AZ возвращается.

  • autoheal: ваша сеть может быть ненадежной. Вас больше заботит непрерывность обслуживания, чем целостность данных. У вас может быть кластер из двух узлов.

этот ответ является ref из RabbitMQ docs. https://www.rabbitmq.com/partitions.html даст вам более подробное описание.