58

我们有一个将使用 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")
4

5 回答 5

39

假设这两种模型都被认为是使用一个运行的代理来实现的,我可以看到几乎没有区别。

选项 2 在现实世界中似乎更常见于解决这种路由问题(至少在我的轶事经验中),而这正是主题交换存在的挑战。

您可能遇到的唯一区别与路由速度有关。#与主题交换中使用的路由密钥技术(可以包括和之类的通配符)相比,我不确定在 RabbitMQ 中交换路由(始终基于精确的字符串匹配)是否更快*。我的预感是 Exchange 歧视会更快,但您可以自己尝试找出答案,或者尝试联系 RabbitMQ 团队询问他们。

最后,如果您选择选项 1 时会出现大量队列,那么您的 Exchange 数量将成比例地增加。这听起来像是一个令人头疼的维护问题。如果您只有少数队列,那么这不会是太大的问题。

于 2012-03-14T20:20:17.783 回答
25

实际上,方法 2 更好,因为它使您可以灵活地使用单个队列来处理多个路由键。

交流话题

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 ...您仍然可以保持单一直接交换。

于 2017-04-25T15:44:43.067 回答
7

对于负载很小的单个小节点,差别不大。大多数人出于上述原因选择选项二。

在设计系统时,您应该问自己将来如何扩展。

它将如何扩展?
我需要它来扩展吗?我以后要添加高可用性集群吗?我的路线会改变吗...

在大多数情况下,选项 2 提供了更多的灵活性。

它允许您使用自己的队列将新的消费者附加到 Exchange 并轻松捕获任何子集或所有消息流。(这些队列可以在集群中的其他节点上或镜像到提供故障转移的 n 个节点)一个典型的用例是使用第 4 个队列记录所有消息。

如果您的瓶颈在处理方面,您还可以进一步细分您的消息主题并执行一些优先级,而无需更改您的发布者。示例:ToppicA.urgent,由专用消费者处理,ToppicA.log 最终处理。

简短的回答是选择选项 2,除非您有非常具体的性能要求,例如,如果您需要处理超过 50k msg/s 的持续速率,您可能需要考虑专用节点上的选项 1,但对于正常流选项 2 将更易于扩展和维护。

于 2015-04-15T05:19:32.330 回答
0

直接交换还支持多条路线(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
于 2019-08-21T20:50:26.520 回答
0

还应该考虑的一件事是,当您发布到不同的交易所与发布到单个交易所但仅使用不同的路由密钥时,您发布消息的代码看起来会略有不同。

请记住,您的代码需要从某个地方(可能来自配置)知道不同交换的名称,并且您必须维护交换和路由键之间的某种映射。同样对于 RabbitMQ 中的直接交换,路由键需要与队列名称完全匹配。因此,您的代码也需要知道队列名称才能设置正确的路由键。

当使用单个交换(无论是直接交换还是主题)时,您的代码只需要处理一个交换和路由键。

于 2020-02-11T15:11:25.943 回答