Кластеризация RabbitMQ: настройка, конфигурация и лучшие практики
Раскройте возможности масштабируемого и отказоустойчивого обмена сообщениями с помощью кластеризации RabbitMQ. Это руководство охватывает основные концепции, такие как типы узлов, сетевые разделы и синхронизация данных. Узнайте пошагово, как настроить кластер RabbitMQ, сконфигурировать очереди высокой доступности (HA) с помощью политик и внедрить лучшие практики для надежного развертывания и управления. Идеально подходит для разработчиков и операторов, стремящихся создавать отказоустойчивые приложения, управляемые сообщениями.
Кластеризация RabbitMQ: настройка, конфигурация и лучшие практики
Кластеризация RabbitMQ часто понимается неправильно. Кластер предоставляет вам один логический брокер, состоящий из нескольких узлов Erlang. Он разделяет пользователей, vhosts, обменники, привязки, политики и другие метаданные между этими узлами. Он не делает автоматически сообщения каждой очереди доступными везде. Доступность очереди зависит от типа очереди и ее настроек репликации.
Эта разница важна в производственной среде. Кластер может упростить управление и маршрутизацию, а также поддерживать очереди высокой доступности, но это не волшебный переключатель производительности. Если вы поместите все горячие очереди на один узел, этот узел все равно будет выполнять работу. Если вы используете классические очереди без репликации и узел-лидер очереди исчезает, эта очередь недоступна до возвращения узла. Проектируйте кластер вокруг очередей, которые вы фактически запускаете.
Что кластер разделяет, а что нет
Метаданные кластера RabbitMQ реплицируются. Если вы объявите обменник на одном узле, другие узлы узнают о нем. Если вы добавите пользователя или политику, кластер сохранит это определение. Клиентские приложения могут подключаться к любому узлу и использовать ту же топологию.
Сообщения — другое дело. У очереди есть лидер. Для классических очередей сообщения живут на узле, который размещает эту очередь, если вы не используете старые зеркальные очереди. Для кворумных очередей RabbitMQ реплицирует данные очереди через группу узлов, используя протокол консенсуса. Для потоков данные реплицируются в соответствии с конфигурацией потока. В современных развертываниях RabbitMQ кворумные очереди обычно являются более безопасным выбором для реплицированных, долговечных рабочих очередей.
Старые статьи часто говорят об "очередях HA" так, как будто это современное значение по умолчанию. В терминологии RabbitMQ это обычно означает классические зеркальные очереди, настроенные политикой. Они все еще существуют в некоторых установках, но кворумные очереди — это направление, которое следует рассмотреть для большинства новых проектов долговечных реплицированных очередей. Всегда проверяйте версию RabbitMQ и эксплуатационные ограничения вашей среды перед миграцией существующей рабочей нагрузки.
Перед присоединением узлов
Сначала выполните скучные проверки:
- Узлы должны последовательно разрешать имена хостов друг друга.
- Порт распространения Erlang и порты RabbitMQ должны быть доступны между узлами.
- Версии RabbitMQ и Erlang должны быть совместимы в рамках кластера.
- Все узлы должны использовать один и тот же файл cookie Erlang.
- Синхронизация времени должна быть разумной, особенно если от нее зависят ваш мониторинг и TLS.
Файл cookie Erlang — это общий секрет, используемый узлами Erlang. Во многих пакетах Linux он находится по адресу /var/lib/rabbitmq/.erlang.cookie, принадлежит пользователю rabbitmq и имеет режим 600.
sudo systemctl stop rabbitmq-server
sudo install -o rabbitmq -g rabbitmq -m 600 .erlang.cookie /var/lib/rabbitmq/.erlang.cookie
sudo systemctl start rabbitmq-server
Не перегенерируйте файл cookie случайно на работающем кластере. Если у одного узла другой файл cookie, он не сможет общаться с другими, и сообщение об ошибке не всегда дружелюбное.
Присоединение узла
Предположим, что rabbit@rmq-a уже запущен, и rabbit@rmq-b должен присоединиться к нему. На rmq-b:
sudo rabbitmqctl stop_app
sudo rabbitmqctl reset
sudo rabbitmqctl join_cluster rabbit@rmq-a
sudo rabbitmqctl start_app
Затем проверьте с любого узла:
rabbitmqctl cluster_status
rabbitmq-diagnostics cluster_status
reset удаляет локальную базу данных RabbitMQ узла перед присоединением. Обычно это то, что вам нужно для нового пустого узла. Это не то, что следует выполнять случайно на узле, который владеет очередями, которые вам важны.
Для трех узлов повторите тот же процесс с rmq-c. Вы можете присоединить как rmq-b, так и rmq-c к rmq-a; после присоединения не существует постоянного "мастер-узла" для метаданных, как иногда представляют люди.
Разместите клиентов за стабильной конечной точкой
Приложения не должны иметь один жестко заданный хост брокера, если вы ожидаете обслуживания узлов. Используйте балансировщик нагрузки, стратегию DNS или список подключений клиентской библиотеки. Балансировщик нагрузки должен проверять, запущено ли приложение RabbitMQ, а не только открыт ли порт 5672.
Простая проверка TCP может отправить клиентов на узел, который жив, но заблокирован тревогами или не полностью присоединен. В более строгих средах используйте проверки работоспособности, предоставляемые через плагин управления, или небольшую локальную проверку, которая выполняет rabbitmq-diagnostics -q ping.
Выбирайте типы очередей осознанно
Для долговечных реплицированных рабочих нагрузок кворумная очередь часто является хорошим значением по умолчанию:
rabbitmqadmin declare queue name=orders.pending durable=true arguments='{"x-queue-type":"quorum"}'
Или через объявление в приложении:
channel.queue_declare(
queue='orders.pending',
durable=True,
arguments={'x-queue-type': 'quorum'}
)
Кворумные очереди жертвуют некоторой пропускной способностью и задержкой ради более сильного поведения репликации. Они не являются бесплатным обновлением для каждой очереди. Для временных очередей ответов, краткосрочных подписчиков fanout или низкоценных временных рабочих нагрузок классические очереди могут быть в порядке. Для бизнес-событий, которые должны пережить потерю узла, используйте реплицированный тип очереди и тестируйте отказоустойчивость.
Сетевые разделы — это операционное событие, а не флажок
Сетевой раздел означает, что узлы кластера не могут общаться друг с другом. У RabbitMQ есть стратегии обработки разделов, но ни одна из них не превращает сломанную сеть в здоровую. Правильный ответ — спроектировать кластер так, чтобы разделы были редкими, видимыми и тщательно восстанавливались.
Для большинства производственных кластеров используйте нечетное количество узлов для рабочих нагрузок на основе кворума и избегайте растягивания небольшого кластера по ненадежным каналам связи. Три узла в трех зонах доступности могут хорошо работать, если задержка приемлема. Два узла, разделенные между двумя сайтами, являются распространенным источником болезненных решений, потому что нет большинства в случае разрыва связи.
После подозрения на раздел проверьте:
rabbitmqctl cluster_status
rabbitmq-diagnostics alarms
rabbitmq-diagnostics check_running
rabbitmqctl list_queues name type leader members online state
Если лидеры очередей переместились или члены стали офлайн, не предполагайте, что приложение в порядке, потому что соединения восстановились. Следите за подтверждениями издателя, частотами ошибок потребителей и неподтвержденными сообщениями.
Привычки обслуживания, предотвращающие сюрпризы кластера
По возможности отключайте соединения перед остановкой узла. Если вы разместили клиентов за балансировщиком нагрузки, удалите узел из ротации, подождите, пока клиенты переподключатся в другом месте, затем перезапустите RabbitMQ.
Периодически проверяйте распределение очередей:
rabbitmqctl list_queues name type leader messages consumers
Если каждый лидер горячей очереди находится на одном узле, кластер не сбалансирован для этой рабочей нагрузки. Возможно, вам потребуется переобъявить очереди, пересмотреть политики или использовать настройки локатора лидера очереди, подходящие для вашей версии RabbitMQ.
Храните политики под контролем версий. Политика, которая изменяет тип очереди, мертвые письма, максимальную длину или поведение зеркалирования, является производственной инфраструктурой, а не настройкой пользовательского интерфейса.
Резервное копирование все еще важно. Кластеризация не заменяет экспорт определений, автоматизацию инфраструктуры или планирование аварийного восстановления. Экспортируйте определения после изменений топологии:
rabbitmqadmin export rabbitmq-definitions.json
Наконец, протестируйте отказ, который, по вашему мнению, вы можете пережить. Остановите узел, который содержит лидера очереди. Убейте потребителя, пока у него есть неподтвержденные сообщения. Заблокируйте издателя во время тревоги диска в тестовой среде. Кластер RabbitMQ заслуживает доверия через скучные репетиции, а не через диаграмму с тремя узлами на ней.