Параметры очереди изменения RabbitMQ в производственной системе

Я использую RabbitMQ как очередь сообщений в сервис-ориентированной архитектуре, где многие отдельные веб-службы публикуют сообщения, связанные с очередями RabbitMQ. Эти очереди, в свою очередь, подписываются различными потребителями, которые выполняют фоновые работы; довольно ванильный вариант использования для RabbitMQ.

Теперь я хотел бы изменить некоторые параметры очереди (в частности, я хотел бы привязать очереди к новому обмену мертвыми буквами с определенным ключом маршрутизации). Моя проблема заключается в том, что внесение такого изменения в производственную систему проблематично по нескольким причинам.

Каков наилучший способ перехода на эти новые очереди без потери сообщений в производственной системе?

Я рассмотрел все из имен очереди версий, чтобы создать новый vhost с новыми настройками для выполнения всех изменений.

Вот некоторые из проблем, с которыми я сталкиваюсь:

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

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

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

Ответ 1

Связывание очередей может быть добавлено и удалено во время выполнения без какого-либо влияния на клиентов, если клиенты не будут вручную изменять привязки. Поэтому, если ваш вопрос только о привязках просто меняет их через панель управления CLI или веб-панелью и пропускает то, что написано ниже.

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

Быстрый и грязный способ:

Пока издатели не занимаются объявлением очередей и привязками (по крайней мере, они не должны этого делать), вы можете сосредоточиться на потребителях. Объявление очереди очередей в блоке try-except может быть быстрым и грязным выбором. Кроме того, большинство проектов, даже многочисленных, могут выдержать небольшое время простоя, поэтому вы можете заблокировать пользователя rabbitmq в одной оболочке, изменить очередь по своему усмотрению (создать новую и заставить своих потребителей использовать ее вместо старой), а затем разблокировать пользователя и позволить пользователям работать как прежде чем (ваши работники находятся под наблюдением или monit, не так ли?). Затем перенесите вручную сообщения из старой очереди в новую.

Быстрое и безопасное решение:

Является немного сложным и основано на взломе, как перенести сообщения из одной очереди в другую внутри одного vhost. Все решение работает внутри одного vhost, но требует дополнительной очереди для каждой очереди, которую вы хотите изменить. Настройте "Мертвые письма" в исходной очереди и укажите, чтобы он пересылал истекшие сообщения в новую целевую очередь. Затем примените "TTL" для очереди сообщений в исходную очередь, установите x-message-ttl=0 (к этому минимальное значение см. No Queuing at сообщить о немедленной доставке). Оба действия могут выполняться через CLI или панель управления и могут выполняться в уже объявленной очереди. Таким образом, ваши издатели могут публиковать сообщения как обычно, и даже старые пользователи могут работать как ожидалось в первый раз, но параллельно новые потребители могут потреблять из новой очереди, которая может быть предварительно объявлена ​​с помощью новых аргументов вручную или иным способом.

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

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

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

P.S.: В любом случае, если можно, пусть старые пользователи пустуют очереди, поэтому вам не нужно вручную переносить сообщения.

Update:

Вы можете найти очень полезный плавник для лопаты, особенно Динамические лопаты перемещать сообщения между обменами и очередями, даже между разными vhosts и серверами. Это самый быстрый и безопасный способ переноса сообщений между очередями/обменами.