RabbitMQ中的主题交换和直接交换

62

我们有一个应用程序将使用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
您可以在此处了解区别: https://dev59.com/r2kw5IYBdhLWcg3ws8z3https://jstobigdata.com/rabbitmq/topic-exchange-in-amqp-rabbitmq/ - SyntaX
5个回答

41

假设两个模型都将使用一个运行代理来实现,我看不出有什么区别。

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

你可能会遇到的唯一区别与路由速度有关。我不确定 RabbitMQ 的 Exchange 路由(始终基于精确字符串匹配)是否比 Topic Exchange 中使用的路由键技术更快(可以包括像 # 和 * 这样的通配符)。我的直觉是 Exchange 区分会更快,但您可以自己进行实验或尝试联系 RabbitMQ 团队询问他们。

最后,如果你选择选项1并最终有很多队列,那么你会有相应数量的交换机,这听起来像是一个维护上的头痛。如果只有少数队列,那么这不会是太大的问题。


2
我同意。使用适当的路由键来创建多个队列更易于管理。我所能想到的选项1唯一的优点是,多个交换机可以托管在单独的硬件上,从而实现垂直扩展。但是,如果您的硬件表现良好,那么您可能永远不需要采取这种方法。 - Steve Martin
3
我认为使用主题的优点是,如果将来需要将相同的消息发送到交换机中的多个队列,则您的第二个选项会更可取。 - gigi2
1
请注意,当有多个消费者时,使用直接交换会像扇出一样将消息发送到所有连接的用户。同时,主题交换队列将基于轮询处理消费者。 - Hany Hassan

27

确实,方法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...您仍然可以使用单一的direct exchange。


保持单个直接交换会影响性能吗? - was_777
为什么我们不能使用fanout代替topic? - ujwal dhakal
由于其不够通用,主题可以像直接和扇出一样起作用。顺便说一句,扇出只会将消息盲目地分发到队列中。 - Shift 'n Tab

7
对于负载较小的单个小节点,两种选择差异不大。由于上述原因,大多数人选择选项二。
在设计系统时,您应该问自己将来会如何扩展?是否需要进行扩展?将来是否想要添加高可用性集群?我的路由是否会改变...
在大多数情况下,选项二提供了更多的灵活性。它使您可以轻松地将新的消费者附加到其自己的队列的交换机,并捕获任何子集或所有消息流(这些队列可以在群集中的其他节点上或镜像到n个节点以提供故障转移)。典型用例是使用第四个队列记录所有消息。
如果瓶颈在于处理方面,您还可以进一步细分消息主题并执行某些优先级排序,而无需更改发布者。例如:ToppicA.urgent由专用消费者处理,TopicA.log最终被处理。
简短的答案是除非您有非常特定的性能要求,否则选择选项2。例如,如果您需要处理超过50k条/秒的持续速率,您可能需要考虑在专用节点上使用选项1,但对于正常流程,选项2将更易于扩展和维护。

1

0

还有一件需要考虑的事情是,当您发布到不同的交换机时,与仅使用不同路由键发布到单个交换机时相比,发布消息的代码将略有不同。

请记住,您的代码需要从某个地方(可能是配置)知道不同交换机的名称,并且您必须维护一种交换机和路由键之间的映射。此外,在RabbitMQ中使用直接交换时,路由键需要完全匹配队列名称。因此,您的代码还需要知道队列名称,以便能够设置正确的路由键。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接