Кластер RabbitMQ не восстанавливает соединение после сбоя сети - PullRequest
13 голосов
/ 28 декабря 2011

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

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

= ИНФОРМАЦИОННЫЙ ОТЧЕТ ==== 23 декабря 2011 г. :: 04: 21: 35 ===
узел кролик @ rabbitmq02 потерянный "кролик"

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

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

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

Мои вопросы:

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

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

Ответы [ 3 ]

14 голосов
/ 10 января 2012

Кластеры 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-адрес. IP.

9 голосов
/ 22 апреля 2014

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

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

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

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

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

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

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

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

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

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

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

9 голосов
/ 10 января 2012

Еще один способ восстановления после такого рода сбоев - это работа с Mnesia, которая является базой данных, которую RabbitMQ использует в качестве механизма сохранения, и для синхронизации экземпляров RabbitMQ (и статуса главного / подчиненного) это контролируется. Все подробности см. По следующему URL: 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_down друг от друга он генерирует {inconsistent_database, начальное_частичное_сеть, системное событие 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: force_load_table (Tab) может использоваться для принудительной загрузки таблица независимо от того, какой механизм загрузки таблицы активирован.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...