Аварийное восстановление RabbitMQ с помощью Federated Exchanges
В этой статье описывается шаблон аварийного восстановления (DR) для RabbitMQ, использующий federated exchanges. В этом шаблоне основной экземпляр или кластер RabbitMQ публикует бизнес-сообщения во upstream exchange, а резервный DR-экземпляр или кластер RabbitMQ использует downstream exchange, который федеративно подключается к upstream exchange.
Federated exchanges обеспечивают асинхронную репликацию сообщений между кластерами для выбранных потоков сообщений. Они подходят для warm-standby-дизайнов, регионального распределения и выборочной репликации. Это не механизм синхронной высокой доступности, и он не заменяет отказоустойчивость приложения, регулярное резервное копирование, управление RabbitMQ definitions или проектирование durable queue.
Содержание
Применимые сценарииКак работает шаблон DRПредварительные требованияВключение Federation pluginsПодготовка RabbitMQ definitions для готовности DRПроцедура1. Подготовьте primary exchange2. Подготовьте DR exchange, queue и binding3. Определите окно удержания backlog в DR4. Настройте federation upstream на DR-кластере5. Примените federation policy к downstream exchange6. Опубликуйте тестовые сообщения в primary exchange7. Проверьте, что DR-сторона получает реплицированные сообщения8. Подготовьте процедуру failover приложенияПроверкаОграничения и замечания по проектированиюУстранение неполадокPlugins не включеныОтсутствуют DR definitionsОтсутствует federation parameter или policyСообщения не появляются на стороне DRПроблемы с аутентификацией, сетью или TLS прерывают linkПосле изменений topology или переподключений появляются дубликаты сообщенийПрименимые сценарии
Используйте federated exchanges, если вам нужно одно или несколько из следующего:
- Поддерживать удалённый кластер RabbitMQ в warm standby с достаточно актуальной копией выбранных потоков сообщений.
- Реплицировать только подмножество exchange вместо полного состояния кластера.
- Переносить временные отказы WAN или межкластерного соединения и автоматически восстанавливать link.
- Подготовить резервную площадку, которая сможет принимать сообщения после переключения producers и consumers в DR-среду.
Federated exchanges обычно не являются правильным решением, если вам нужно одно или несколько из следующего:
- Строгая гарантия
RPO=0. - Синхронная репликация без потерь между кластерами.
- Автоматический failover producers или consumers на стороне приложения.
- Автоматическая синхронизация пользователей RabbitMQ, permissions, exchanges, queues, bindings, policies, TLS-материалов, ресурсов Kubernetes или конфигурации приложения.
- Замена резервного копирования, восстановления или планирования durable storage.
Как работает шаблон DR
В этом примере:
rabbitmq-primaryразмещает upstream exchangeapp.events.rabbitmq-drразмещает downstream exchangeapp-events-dr.- На
rabbitmq-drнастроен federation link. - Policy на
rabbitmq-drвыбираетapp-events-drкак federated exchange. - Bindings на downstream-стороне определяют, какие сообщения запрашиваются у upstream-стороны.
Концептуально сообщения, опубликованные в app.events на основной стороне, копируются в app-events-dr на стороне DR так, как если бы они были опубликованы локально в downstream exchange.
Используйте такие имена exchange, queue и binding, которые соответствуют вашему плану failover приложения. В примере используются разные имена primary и DR exchange, чтобы направление было явно видно. Если после failover приложения должны использовать одни и те же имена exchange или queue, объявите эти имена в DR-кластере и последовательно обновите команды.
Federation links являются асинхронными. Во время сетевого разделения, ошибки аутентификации или недоступности upstream сообщения могут отставать или быть недоступны на стороне DR, пока link не восстановится. Не описывайте этот шаблон как синхронный HA или гарантированную репликацию без потерь.
Предварительные требования
Перед настройкой federated exchanges убедитесь, что выполнены следующие условия:
- У вас есть два доступных экземпляра или кластера RabbitMQ, которые в этой статье называются
rabbitmq-primaryиrabbitmq-dr. - В downstream DR-кластере включён plugin
rabbitmq_federation. - Включайте
rabbitmq_federation_managementна downstream DR-кластере только в том случае, если вам нужны страницы federation в management UI или API. - Upstream primary-кластеру не нужны
rabbitmq_federationилиrabbitmq_federation_managementдля federated exchanges. - Вы можете достичь upstream AMQP listener со стороны DR через
<primary-host>:<primary-port>. - У вас есть доступ к management UI или CLI для обеих сред.
- Upstream user в federation URI имеет права на подключение к требуемому virtual host и доступ к upstream exchange.
- Вам известны адреса доступа, учётные данные и значения namespace, соответствующие вашей среде.
- RabbitMQ definitions, необходимые для failover приложения, уже спланированы для DR-среды.
Также необходимо учитывать следующие требования к проектированию:
- Используйте durable exchange и durable queue для важных потоков сообщений.
- Публикуйте persistent сообщения, если рабочая нагрузка требует восстановления после перезапуска broker.
- Делайте consumers идемпотентными, поскольку дубликаты всё ещё могут возникать во время переподключений, изменений topology или многопутевой маршрутизации.
- Избегайте двунаправленных или mesh-топологий, если вы явно не спроектировали предотвращение циклов и обработку дубликатов.
Включение Federation plugins
Требование к plugin для этого шаблона находится на downstream DR-кластере. Включите rabbitmq_federation на rabbitmq-dr. Включайте rabbitmq_federation_management на rabbitmq-dr только если вам нужны страницы federation в management UI или API. Upstream primary-кластеру plugins federation не нужны.
В следующем примере primary-кластер остаётся без конфигурации federation plugin, а plugins включаются на DR-кластере с использованием spec.rabbitmq.additionalPlugins.
После того как оператор выполнит rollout обновлённого StatefulSet, проверьте, что plugins включены на стороне DR:
В выводе должен присутствовать rabbitmq_federation. Если вы включили management plugin, в выводе также должен присутствовать rabbitmq_federation_management.
Подготовка RabbitMQ definitions для готовности DR
Federation перемещает выбранные сообщения между exchange. Она не синхронизирует topology приложения, security definitions или ресурсы платформы. Перед переключением на DR в DR-кластере должны уже существовать virtual hosts, exchanges, queues, bindings, users, permissions, policies, parameters, TLS-материалы, объекты Kubernetes Secret и конфигурация приложения, которые требуются рабочей нагрузке.
Используйте один из следующих подходов:
- Если RabbitMQ definitions управляются через GitOps, bootstrap-код приложения или другой декларативный процесс, примените те же целевые definitions к DR-кластеру и проверьте их там.
- Если primary topology уже существует и не управляется декларативно, экспортируйте definitions из primary-кластера и импортируйте проверенные definitions в DR-кластер.
Экспорт и импорт definitions — это операция на определённый момент времени. Область действия зависит от того, выполняете ли вы экспорт на уровне всего кластера или экспорт для одного vhost:
- Используйте экспорт на уровне всего кластера, когда DR-кластер нужно заполнить virtual hosts, users, permissions, exchanges, queues, bindings, runtime parameters и policies.
- Используйте экспорт для одного vhost только тогда, когда целевой virtual host, users и permissions уже подготовлены в DR-кластере, и вам нужно перенести только topology для этого virtual host. В RabbitMQ 3.8.16 файл
rabbitmqadmin --vhost / export ...содержит ключи topology в пределах vhost, такие какexchanges,queues,bindings,parametersиpolicies, но не включаетusers,permissionsилиvhosts.
Экспорт и импорт definitions не копируют содержимое queue, durable message stores, stream data, ресурсы Kubernetes, TLS key material, хранящийся вне RabbitMQ, или конфигурацию приложения.
Для готовности DR экспортируйте cluster-wide definitions из primary-кластера, если только вы намеренно не хотите получить файл topology только для одного vhost:
Перед импортом проверьте primary-definitions.json. Удалите или скорректируйте definitions, специфичные для основной площадки, такие как upstream URI, параметры shovel, policies, которые не должны применяться в DR, test users или topology, которая намеренно отличается между площадками. Относитесь к файлу как к чувствительным данным, поскольку он может содержать хэши паролей пользователей и эксплуатационную конфигурацию.
Импортируйте проверенные cluster-wide definitions в DR-кластер:
Если вам нужно перенести только topology для virtual host, который уже существует в DR-кластере, укажите --vhost <vhost> и в командах экспорта, и в командах импорта:
Проверьте definitions, которые требуются приложениям после failover:
Если вы импортировали cluster-wide definitions, также проверьте, что необходимые virtual hosts, users и permissions присутствуют:
Если вы импортируете primary definitions и всё ещё используете специфичные для DR downstream exchange или queue, создайте эти специфичные для DR объекты после импорта. Процедура ниже явно объявляет примерные объекты. Если ваши DR definitions уже содержат эквивалентные объекты, проверьте их и пропустите команды повторного объявления.
Процедура
1. Подготовьте primary exchange
Объявите upstream exchange на rabbitmq-primary. В примере ниже используется durable topic exchange с именем app.events.
В командах ниже rabbitmqadmin подключается к management endpoint RabbitMQ, например к порту 15672. Позже настроенный federation upstream URI должен использовать AMQP listener, например 5672 для amqp:// или 5671 для amqps://.
Если ваши приложения уже публикуют сообщения в существующий exchange, используйте это имя exchange вместо создания нового.
2. Подготовьте DR exchange, queue и binding
Объявите downstream exchange, DR queue и binding на rabbitmq-dr. Объявите queue один раз, а затем используйте queue policy для удержания сообщений вместо повторного объявления queue с другими аргументами.
Downstream binding определяет, какие routing keys запрашиваются у upstream-стороны. Изменения binding распространяются асинхронно, поэтому дайте системе немного времени, прежде чем ожидать применения нового поведения фильтрации.
3. Определите окно удержания backlog в DR
Federated exchanges лучше всего рассматривать как шаблон bounded warm-standby. DR-сторона должна удерживать сообщения в течение заданного окна, а не позволять им накапливаться без ограничения, пока standby consumers остановлены.
Используйте message TTL на DR queue, чтобы определить, как долго сообщения могут оставаться в standby backlog. Не задавайте expires или x-expires для этой durable standby queue. Queue expiration удаляет неиспользуемую queue после периода бездействия. В warm-standby-дизайне у DR queue могут намеренно отсутствовать активные consumers в течение длительного времени, поэтому queue expiration может удалить queue и накопленный DR backlog.
В следующем примере сообщения в app-events-dr-q сохраняются до 24 часов с помощью queue policy:
Если к DR queue уже применяется другая queue policy, добавьте message-ttl в эту policy вместо создания конкурирующей policy. На queue может влиять приоритет policy, поэтому после изменения проверьте активную policy.
Проверьте policy и queue:
В этом примере standby backlog ограничен окном хранения сообщений в 24 часа. Более короткие значения уменьшают рост объёма диска, но сужают окно восстановления. Более длинные значения увеличивают объём доступной standby-истории во время failover, но также увеличивают использование диска и риск накопления backlog на стороне DR.
Выбирайте окно удержания в соответствии с:
- Допустимой точкой восстановления для рабочей нагрузки.
- Ожидаемым пиковым объёмом сообщений во время отказа основной площадки.
- Объёмом хранилища, доступным в DR-кластере.
4. Настройте federation upstream на DR-кластере
Выполните следующую команду на rabbitmq-dr, чтобы создать federation upstream с именем primary-app-events:
Эта конфигурация означает следующее:
uri: адрес AMQP-подключения к upstream RabbitMQ-кластеру. Завершающий символ%2f— это URL-кодированная форма virtual host по умолчанию/. Если upstream exchange находится в виртуальном host, отличном от default, замените%2fна URL-кодированное имя upstream virtual host.exchange: upstream exchange, из которого выполняется потребление.max-hops: ограничивает количество federation link, через которые может пройти сообщение, и помогает избежать циклов.reconnect-delay: управляет тем, сколько времени link ждёт перед повторным подключением после разрыва.
Если ваша среда требует TLS, используйте URI amqps:// и соответствующие параметры TLS-подключения, поддерживаемые RabbitMQ AMQP URIs.
5. Примените federation policy к downstream exchange
Примените policy на rabbitmq-dr, чтобы downstream exchange app-events-dr использовал upstream definition.
Проверьте, что upstream parameter и policy присутствуют:
6. Опубликуйте тестовые сообщения в primary exchange
Опубликуйте одно или несколько persistent тестовых сообщений в app.events на rabbitmq-primary.
7. Проверьте, что DR-сторона получает реплицированные сообщения
Проверьте queue, привязанную к downstream exchange на rabbitmq-dr, не удаляя backlog:
Если federation работает, DR queue будет получать сообщения, опубликованные в upstream exchange, с routing keys, соответствующими downstream binding. ack_requeue_true возвращает проверенные сообщения обратно в queue, чтобы standby backlog не потреблялся во время проверки. Если вы выполняете проверку с одноразовыми тестовыми сообщениями или одноразовой тестовой queue, после подтверждения безопасности для вашего DR-плана можно использовать режим destructive acknowledgment.
8. Подготовьте процедуру failover приложения
Federation перемещает только выбранные потоки сообщений. Она не переключает приложения автоматически. Для фактического DR failover определите шаги на стороне приложения, необходимые для следующего:
- Перенаправить producers на
rabbitmq-dr. - Перенаправить consumers на
rabbitmq-dr. - Подтвердить, что необходимые exchanges, queues, bindings, users, policies, TLS-материалы, ресурсы Kubernetes и application secrets уже существуют на стороне DR.
- Подтвердить, что backlog DR queue находится в пределах окна message TTL, которое ожидает ваш план восстановления.
- Определить, как возобновить или согласовать трафик, когда основная площадка снова станет доступна.
Проверка
После настройки используйте следующие проверки:
Если вы также включите rabbitmq_federation_management на DR-кластере, вы сможете просматривать конфигурацию federation и состояние выполнения на соответствующих страницах federation в management UI.
Ограничения и замечания по проектированию
При использовании federation для DR учитывайте следующие ограничения:
- Репликация асинхронная, поэтому задержка ожидаема при нормальной работе и может увеличиваться при сетевых проблемах.
- Federated exchange не заменяет проектирование mirrored или quorum queue, persistent storage или резервного копирования.
RPO=0не гарантируется. Сообщения могут быть задержаны или отсутствовать на стороне DR, когда links недоступны.- Federation не синхронизирует RabbitMQ definitions. Управляйте definitions отдельно через export/import, GitOps, bootstrap-код приложения или другой контролируемый процесс.
- Экспорт и импорт definitions — это операция snapshot. Повторяйте её или обновляйте DR definitions каждый раз, когда изменяются primary topology, users, permissions, parameters или policies.
- Downstream bindings влияют на то, что копируется из upstream. Обновления binding применяются не мгновенно, а со временем.
- Сообщения, отправленные напрямую в downstream exchange, не отражаются обратно в queue, привязанные только на upstream-стороне.
- Default exchange и internal exchanges не могут быть федеративно связаны.
max-hopsпомогает избегать циклов, но не устраняет все сценарии дубликатов в сложных topology.- Durable exchange и queues снижают риск восстановления, но не превращают federation из асинхронной в синхронную репликацию.
- Message TTL определяет практическое окно backlog для warm standby. Большие значения увеличивают доступное окно повторного воспроизведения, но также увеличивают потребление диска на стороне DR.
- Queue expiration не следует использовать для durable standby queue, которая должна сохраняться длительное время без consumers.
- Аутентификация, авторизация, DNS, порты, firewall rules и доверие к TLS certificate должны быть настроены корректно, чтобы link оставался в рабочем состоянии.
Устранение неполадок
Plugins не включены
Симптом:
rabbitmq-plugins list -e на rabbitmq-dr не показывает rabbitmq_federation или не показывает rabbitmq_federation_management, когда вы ожидаете поддержку management UI или API.
Проверки:
- Убедитесь, что
spec.rabbitmq.additionalPluginsнаrabbitmq-drвключаетrabbitmq_federation. - Если вам нужны страницы federation management UI или API, убедитесь, что
spec.rabbitmq.additionalPluginsнаrabbitmq-drтакже включаетrabbitmq_federation_management. - Проверьте, были ли pod RabbitMQ DR перезапущены после изменения spec.
Рекомендация:
Обновите ресурс RabbitmqCluster rabbitmq-dr, дождитесь завершения rollout и снова проверьте plugins в DR-кластере.
Отсутствуют DR definitions
Симптом:
Federation настроена, но producers или consumers завершаются с ошибкой после failover, потому что отсутствуют exchanges, queues, bindings, users, permissions, policies или TLS-материалы на rabbitmq-dr.
Проверки:
- Убедитесь, управляются ли definitions через GitOps, bootstrap-код приложения или экспорт и импорт RabbitMQ definitions.
- На
rabbitmq-drперечислите exchanges, queues, bindings, users, permissions, parameters и policies, требуемые приложением. - Убедитесь, что объекты Kubernetes
Secret, сертификаты и конфигурация подключения приложения также подготовлены для DR-среды. - Если definitions были импортированы, убедитесь, что site-specific definitions были проверены и скорректированы перед импортом.
Рекомендация: Синхронизируйте необходимые RabbitMQ definitions и ресурсы платформы до объявления DR-площадки готовой. Не полагайтесь на federation для создания application topology или security definitions.
Отсутствует federation parameter или policy
Симптом:
rabbitmqctl list_parameters -p / или rabbitmqctl list_policies -p / на rabbitmq-dr не показывает ожидаемые объекты.
Проверки:
- Повторно выполните команды
set_parameterиset_policy. - Убедитесь, что команды выполнялись на DR-кластере и для правильного virtual host.
- Подтвердите, что pattern policy точно соответствует имени downstream exchange.
- Выполните
kubectl exec -n <namespace> rabbitmq-dr-server-0 -- rabbitmqctl federation_status, чтобы проверить, отсутствует ли link или он остановлен.
Рекомендация: Создайте parameter и policy заново с правильными virtual host, именем exchange и pattern policy.
Сообщения не появляются на стороне DR
Симптом:
Публикация в app.events проходит успешно, но app-events-dr-q остаётся пустой.
Проверки:
- Убедитесь, что upstream exchange — это
app.events, а downstream exchange —app-events-dr. - Убедитесь, что downstream queue привязана к
app-events-drс ожидаемым routing key. - Опубликуйте routing key, который соответствует downstream binding, например
orders.created. - Дайте время на асинхронное распространение binding и повторное подключение link.
- Проверьте
rabbitmqctl federation_statusнаrabbitmq-dr. Здоровый link обычно имеет состояниеrunning. - Проверьте, не истёк ли message TTL у старых тестовых сообщений до того, как вы их прочитали.
Рекомендация: Исправьте имена exchange, pattern binding, routing key или окно удержания, а затем повторите тест.
Проблемы с аутентификацией, сетью или TLS прерывают link
Симптом: Upstream parameter существует, но репликация выполняется нестабильно.
Проверки:
- Убедитесь, что
<primary-host>:<primary-port>доступен из RabbitMQ pod DR. - Убедитесь, что пользователь в upstream URI может подключаться к upstream virtual host.
- Если используется TLS, проверьте доверие к сертификату и используйте
amqps://в upstream URI. - Выполните
kubectl exec -n <namespace> rabbitmq-dr-server-0 -- rabbitmqctl federation_statusи проверьте, находится ли link в состоянииstoppedили показывает повторяющиеся ошибки.
Рекомендация: Сначала устраните проблемы с соединением или учётными данными, а затем дождитесь повторного подключения federation link.
После изменений topology или переподключений появляются дубликаты сообщений
Симптом: Consumers на стороне DR получают дубликаты бизнес-событий.
Проверки:
- Убедитесь, что
max-hopsзадан консервативно, например1для простой topology primary-to-DR. - Проверьте, не настроили ли вы случайно несколько upstream или двунаправленные links.
- Проанализируйте поведение приложения во время переподключений и повторных попыток.
Рекомендация:
Упростите topology, держите max-hops на низком уровне и сделайте consumers идемпотентными.