Необходим отдельный обмен мертвыми письмами в RabbitMQ?

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

Блок-схема, изображающая предполагаемый поток сообщений. Описание ниже.

Создаваемые извне входящие сообщения направляются на обмен, который помещает их в рабочую очередь. Во время обработки сообщения потребитель может выйти из строя из-за некоторых временных ошибок (представьте, что поисковый робот получает ошибку 500 с веб-сайта).
Вместо того, чтобы отклонить сообщение и снова поместить его в начало очереди (что приведет к бесконечный цикл), мы маршрутизируем отклоненные сообщения (с requeue=0) на обмен, добавляя очередь недоставленных сообщений в качестве ключа маршрутизации. Здесь каждое сообщение получает TTL в X секунд, после чего оно будет отклонено и, следовательно, направлено обратно на обмен с ключом маршрутизации, установленным в исходную рабочую очередь.

Однако, глядя на литературу и примеры в Интернете, кажется, что все рекомендуют перенаправить на отдельный обмен недоставленными письмами:

Блок-схема, изображающая обычно используемый поток сообщений. Описание ниже.

Создаваемые извне входящие сообщения направляются на рабочий обмен, который помещает их в рабочую очередь. В случае сбоя потребителя сообщения отклоняются (с requeue=0) и перенаправляются на обмен недоставленными сообщениями. Обмен недоставленными сообщениями направляет сообщения в очередь недоставленных сообщений, где истекает срок жизни сообщения, а повторно отклоненные сообщения будут перенаправлены обратно в рабочий обмен.


Есть ли какие-то решающие преимущества у второй конструкции по сравнению с первой? Я не могу определить ни одного, но опять же, я не слишком уверен в RabbitMQ.


person Moritz Friedrich    schedule 03.10.2020    source источник


Ответы (1)


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

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

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

  • Первоначальное сообщение подтверждается потребителем и вручную повторно публикуется для начала обмена. Это обеспечивает некоторую дополнительную гибкость, такую ​​как установка настраиваемых заголовков в сообщении и наличие нескольких очередей задержки с разными TTL, прикрепленными к одной и той же рабочей очереди.
  • Начальный обмен - это разветвленный обмен с привязкой к определенной очереди ожидания, как на второй диаграмме.
  • Когда TTL сообщения истекает в очереди ожидания, оно направляется в отдельный обмен завершенными сообщениями, установленный как обмен недоставленными сообщениями.
  • Этот обмен также является обменом разветвления, только с привязкой к исходной рабочей очереди. Это гарантирует, что дополнительные копии сообщения не будут созданы для других очередей, которые успешно обработали его в первый раз.
  • Таким образом, сообщение возвращается в исходную очередь с исходным ключом маршрутизации.
person IMSoP    schedule 08.10.2020