Обмен темами и прямой обмен в RabbitMQ
У нас есть приложение, которое будет использовать RabbitMQ и иметь несколько разных очередей для передачи сообщений между уровнями.
Вначале я планировал использовать несколько прямых обменов, по одному для каждого типа сообщений, но похоже, что один обмен тегами с очередями, использующими разные привязки ключей маршрутизации, достигнет того же.
Наличие единого обмена также похоже на то, что было бы немного легче поддерживать, но мне было интересно, есть ли какая-либо польза (если таковая имеется) в том, чтобы делать это одним способом над другим?
Вариант 1, используя несколько прямых обменов:
ExchangeA (type: direct)
-QueueA
ExchangeB (type: direct)
-QueueB
ExchangeC (type: direct)
-QueueC
Вариант 2, используя единый обмен темами:
Exchange (type: topic)
-QueueA (receives messages from exchange with routing key of "TypeA")
-QueueB (receives messages from exchange with routing key of "TypeB")
-QueueC (receives messages from exchange with routing key of "TypeC")
Ответы
Ответ 1
Предполагая, что обе модели считаются реализованными с использованием одного брокера, мало различий, которые я вижу.
Вариант 2 кажется более распространенным в реальном мире для решения этой проблемы маршрутизации (по крайней мере, в моем анекдотическом опыте), и это именно то, что существует для обмена Темами.
Единственная разница, с которой вы могли столкнуться, будет связана с скоростью маршрутизации. Я не уверен, что если маршрутизация Exchange (основанная всегда на точном совпадении строк) работает быстрее в RabbitMQ по сравнению с технологией ключа маршрутизации, используемой в разделе "Обмен тегами" (которая может включать в себя подстановочные знаки, такие как #
и *
). Моя догадка заключалась в том, что дискриминация Exchange будет быстрее, но вы можете поэкспериментировать для себя, чтобы узнать, или попытаться связаться с командой RabbitMQ, чтобы спросить их.
Наконец, если вы перейдете с опцией 1 в конечном итоге с большим количеством очередей, тогда у вас будет пропорциональное распространение Exchange. Это звучит как головная боль обслуживания. Если у вас будет только несколько очередей, это не будет проблемой.
Ответ 2
Действительно, подход 2 лучше, поскольку он дает вам гибкость в использовании одной очереди для нескольких ключей маршрутизации.
Тема Exchange
QueueA-- binding key = India.Karnataka.*
Вы можете направлять сообщение на тему обмена с помощью ключа маршрутизации, как India.Karnataka.bangalore, India.Karnataka.Mysore.
Все вышеперечисленные сообщения отправляются в QueueA.
Прямой обмен
Но я не понял, почему вы создаете несколько прямых обменов в подходе 1. Вы можете иметь один прямой обмен и иметь несколько очередей с каждой привязкой к очереди с помощью уникального ключа.
QueueA-- binding key = Key1
QueueB-- binding Key = Key2
QueueC-- binding Key = Key3
Все сообщения key1 отправляются в QueueA.Key2 переходит в QueueB... Вы все равно можете поддерживать один прямой обмен.
Ответ 3
Для небольшого небольшого node с небольшой нагрузкой разница незначительна. Большинство людей идут по варианту два по указанным выше причинам.
При проектировании системы вы должны спросить себя, как это может расширяться в будущем.
Как это будет масштабироваться?
Нужно ли мне это масштабировать?
Должен ли я добавить кластер с высокой степенью доступности в будущем?
Будет ли моя маршрутизация изменяться...
Вариант 2 обеспечивает большую гибкость в большинстве случаев.
Он позволяет делать такие вещи, как прикрепление нового потребителя к Exchange со своей собственной очередью и легко захватывать любые подмножества или весь поток сообщений. (эти очереди могут быть на других узлах кластера или зеркалированы до n узлов, обеспечивающих переход на другой ресурс). Типичным примером использования будет запись всех сообщений с использованием 4-й очереди.
Если ваше узкое место находится на стороне обработки, вы также можете разделить ваши темы сообщений и выполнить некоторую приоритизацию, не изменив своих издателей. Пример: ToppicA.urgent, обработанный выделенным пользователем, в конечном итоге обработано в TextA.log.
Короткий ответ идет с опцией 2, если у вас нет особых требований к производительности. Если, например, вам нужно обработать, скажем, устойчивую скорость более 50 тыс. msg/s, вы можете подумать о опции 1 на выделенных узлах, но для обычных потоков вариант 2 будет легче масштабироваться и обслуживаться.
Ответ 4
Прямой обмен также поддерживает несколько маршрутов (https://www.rabbitmq.com/tutorials/amqp-concepts.html#exchange-direct), так почему бы не использовать что-то вроде этого:
ExchangeA (type: direct)
-QueueA
-RoutingA
ExchangeB (type: direct)
-QueueB
-RoutingB
ExchangeC (type: direct)
-QueueC
-RoutingC