Сбой кластера RabbitMQ после сбоя сети

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

= ОШИБКА ОТЧЕТА ==== 23-Дек-2011:: 04: 21: 34 ===
** Node кролик @rabbitmq02 не отвечает **
** Снятие (время) соединения **

= ИНФОРМАЦИОННЫЙ ОТЧЕТ ==== 23-Дек-2011:: 04: 21: 35 ===
Node кролик @rabbitmq02 потерял "кролика"

= ОШИБКА ОТЧЕТА ==== 23-Дек-2011:: 04: 21: 49 ===
Mnesia (кролик @rabbitmq01): ** ОШИБКА ** mnesia_event получил {inconsistent_database, running_partitioned_network, rabbit @rabbitmq02}

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

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

Мои вопросы:

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

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

Ответ 1

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 2

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

Чтобы определить, есть ли у вас сломанный кластер, выполните команду:

rabbitmqctl cluster_status

для каждого из узлов, входящих в состав кластера. Если кластер сломан, вы увидите только один node. Что-то вроде:

Cluster status of node [email protected] ...
[{nodes,[{disc,[[email protected]]}]},{running_nodes,[[email protected]]}]
...done.

В таких случаях вам нужно будет запустить следующий набор команд на одном из узлов, которые составляют часть исходного кластера (так что он соединяет другой мастер node (скажем, rabbitmq1) в кластере как ведомый):

rabbitmqctl stop_app

rabbitmqctl reset

rabbitmqctl join_cluster [email protected]

rabbitmqctl start_app

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

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

Ответ 3

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

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

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

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

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

Какой режим выбрать?

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

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

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

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

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

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