RabbitMQ. Shovel plugin
Основная идея данной статьи — рассказать, в каких случаях можно использовать shovel плагин, как его активировать и настроить, а также объяснить разницу между динамическим и статическим объявлением shovel плагина.
Использование Shovel plugin
Иногда может возникнуть ситуация, когда необходимо надежно и постоянно перемещать сообщения из источника (например, очередь — queue) одного маршрутизатора в другой маршрутизатор (например, точка обмена — exchange).
Shovel (буквально «лопата») — механизм передачи сообщений из одного объекта (очереди) в другой. Объекты могут принадлежать как одному серверу, так и разным. При этом на целевом сервере Shovel plugin может быть неактивен, а начиная с версии 3.7 даже могут использовать разные версии протоколов — AMQP 0.9.1 или AMQP 1.0.
Сценарий использования: необходимость передать сообщение из одного приложения в другое, при этом каждое из приложений взаимодействует только с одним виртуальным хостом (Virtual host) и ничего не знает о другом приложении.
Существует 2 способа объявления shovel: статический и динамический. Различия между ними приведены в таблице ниже:
Установка и настройка
Установка
Для использования возможностей плагина его необходимо просто включить. Для этого нужно выполнить команды из каталога sbin:
rabbitmq-plugins enable rabbitmq_shovel rabbitmq_shovel_management
Далее потребуется перезапуск RabbitMQ service.
После этого появятся новые секции в меню Admin:
Настройка
Важно отметить, что разобранные далее примеры были выполнены на версии RabbitMQ 3.3.5. Поэтому названия некоторых переменных могут отличаться или отсутствовать обязательные переменные.
До того как рассказывать подробнее о типах shovel, необходимо внести больше ясности о режимах подтверждения сообщений:
- on-confirm — самый медленный, но и самый надежным режим обработки, т.к. сообщение практически невозможно потерять при сбоях. Удаление (ack) происходит после того, как получено подтверждение получения в пункте назначения (опубликовано в queue);
- on-publish — “золотая середина” по скорости и надежности. Удаление (ack) происходит после того, как сообщение отправлено в пункт назначения (опубликовано в exchange). Сообщения могут быть потеряны в случае неполадок на принимающем сервере RabbitMQ;
- no-ack — самый быстрый, но при этом ненадежный, т.к. сообщение удаляется сразу без ожидания ответа. Сообщения могут быть потеряны из-за сбоев сетевой инфраструктуры или сервера RabbitMQ.
Статическое определение
Для того чтобы создать статический shovel, необходимо описать его в файле конфигурации rabbitmq.config в секции rabbitmq_shovel:
Давайте разберёмся, что же было настроено:
- Строки 299-316 описывают источник (source). В данном случае мы указываем, из какой точки обмена (exchange) необходимо будет забирать сообщения, а также привязку очереди и точки обмена.
- Строки 317-328 описывают получателя (receiver). В качестве получателя мы указываем exchange. Обратите внимание, что в данном случае происходит перенаправление из одной точки обмена в другую точку обмена, но уже на другом сервере. Важно отметить, если в секцию publish_fields добавить {routing_key, <<«{{some_routing_key}}»>>} будет происходит замена исходного routing_key на {{some_routing_key}}.
- Строки 329-332 описывают поведение shovel: сколько может обрабатываться за один раз сообщений (prefetch_count), режим подтверждения (ack_mode) и т.п.
После перезапуска сервера RabbitMQ можно увидеть, что был создан статический shovel, который будет перенаправлять сообщения из локального сервера с Virtual host — host2, на удалённый сервер с Virtual host — host_3. При этом, если возникнут какие-то проблемы в конфигурации, например, неверно заданы данные авторизации, необходимо будет выполнять перезапуск сервера.
Динамическое определение
При динамическом определении создать shovel можно несколькими способами:
- используя утилиту rabbitmqctl;
- используя Rest API;
- через Web UI.
Рассмотрим на примере Rest API. Для этого отправим PUT-запрос по адресу /api/parameters/shovel/{{virtual_host}}/{{shovel_name}}, создающий shovel, который:
- Будет забирать сообщения с локального сервера на host-е — host1 из очереди test1_q.
- Отправит сообщение на локальный сервер на host — host2, в exchange
TEST2. - Переподключение выполняется в течение 10 секунд, за один раз забирается 2 сообщения. Подтверждение происходит после того, как сообщения подтверждаются в пункте назначения.
Итоговое тело запроса в формате json:
{
«value»: {
«src-uri»: «amqp://user@/host1»,
«src-queue»: «test1_q»,
«dest-uri»: «amqp://user@/host2»,
«dest-exchange»: «TEST2»,
«ack-mode»: «on-confirm»,
«reconnect-delay»: 10,
«prefetch-count»: 2
}
}
В результате выполнения запроса появится новый shovel:
Важно отметить, что при динамическом определении shovel можно заглянуть “под капот” и увидеть какие параметры были заданы в том или ином случае. Также, если shovel больше не нужен, его можно удалить в нажатием нескольких кнопок в UI не останавливая сервер.
Выводы
Shovel плагин является мощным и гибким инструментом для переотправки сообщений между серверами RabbitMQ или внутри одного сервера. При этом важно понимать, что его задача заключается не в том, чтобы не перенаправлять большой поток сообщений от “верхнеуровневых” серверов RabbitMQ к серверами “нижнего” уровня. Для это цели лучше подойдёт Federation плагин.
Когда использовать статическое или динамическое объявление shovel, нужно решать в каждом отдельном случае, если требуется больше гибкости в настройке и скорости создания — лучше использовать динамическое объявление. Если же изменения в конфигурации не будут вноситься, и нужна большая надежность, тогда лучше будет использовать статистическое объявление.