2012-03-14 46 views
36

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

回答

29

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

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

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

最后,如果你选择1结束了大量的队列,那么你将有一个交易所的比例激增。这听起来像是一个维修头痛。如果你只有少数队列,那么它不会成为太多问题。

+2

我同意。使用适当的路由密钥的多个队列更容易管理。想到选项1的唯一优点是可以在单独的硬件上托管多个交换机,从而实现垂直缩放。但是,如果你的硬件很不稳定,那么你可能永远都不需要采用这条路线。 – 2012-03-14 22:03:01

+0

我认为使用Topic的好处在于,如果将来您需要将相同的消息发送到交换中的多个队列,那么您的选项2会更可取。 – gigi2 2014-04-03 18:02:38

3

对于负载很小的单个小节点,几乎没有区别。由于上述原因,大多数人都选择了第二种选择。

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

它如何扩展?
我需要它来缩放吗? 我想在未来添加高可用性群集吗? 我的路由将改变...

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

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

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

简短的答案与选项2一起使用,除非您有非常特定的性能要求。例如,如果您需要处理超过50k msg/s的持续速率,则可能需要考虑专用节点上的选项1,但对于正常流量,选项2将更容易扩展和维护。

4

实际上,方法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 ......你仍然可以保持单一的直接交换。