与 RabbitMQ 的主题交换歧义

Posted

技术标签:

【中文标题】与 RabbitMQ 的主题交换歧义【英文标题】:Topic exchange ambiguity with RabbitMQ 【发布时间】:2014-08-01 07:33:59 【问题描述】:

我有点困惑。我正在尝试实施主题交换,但不确定需要什么。

我想要几个路由键和 1 个主题交换(默认 amq.topic)。我的钥匙是这样的:

customer.appA.created customer.appB.created customer.*.created

我希望我的队列是持久的,但我需要 1 个“客户”队列还是 appA 和 appB 的 2 个队列? 我已经弄清楚了我的出版商; 连接、交换声明、基本发布

但我正在与消费者斗争。假设我要打开 3 个控制台,每个控制台对应上述路由键。 我当前的消费者有:连接、交换声明、队列绑定、基本消费。这些连接到一个持久的“客户”队列。但是,我的消息被轮询到每个控制台/消费者,而不是使用路由键。

所以我的问题;

    对于典型的主题交换设置;你需要多少个队列? 我的消费者可以只使用交换绑定,还是必须包括队列交互? 单条消息是否可以通过主题交换出现在 2 个消费者中(或者您是否需要为此进行扇出)?

【问题讨论】:

你能指定你使用什么客户端库或扩展吗? videlalvaro/php-amqplib。但这更像是一个抽象/上下文问题。 php-amqp 扩展和 php-amqplib 库之间存在一些差异,因此在特定情况下使用哪一个很重要。例如,使用 php-amqplib 你可以同时从多个队列中消费,而使用 php-amqp 你不能。 【参考方案1】:

第一件事:交换不交付给消费者。它将消息传递到队列以匹配路由键。

      1. For a typical topic exchange set up; how many queues do you need?

如果您有多个消费者,那么每个消费者都需要一个队列。

      2. Can my consumers get away with just exchange binding, or does it have to include queue interaction?

您需要将消费者与队列绑定,如果队列不存在则创建并绑定。

      3. Is it possible for a single message to appear in 2 consumers with topic exchange (or do you need fanout for that)?

是的,只有消费者有自己的(单独的队列绑定相同的路由键)。否则它将是循环方式。

所以最好的方法是让消费者拥有自己的队列和所需的路由键......!!!

【讨论】:

谢谢。我一直以直接的方式思考它。所以我想每个消费者的匿名队列将是要走的路吗? 是的,我已经实现了相同的,在运行时创建队列并将其与您的路由键绑定,然后为它启动消费者。如果您想确保队列在不使用时被删除,也可以使用“x-expires”。 If you have multiple consumer then you will need one queue for every consumer - 这个说法是错误的。您可以将多个消费者附加到同一个队列,也可以在一个通道内同时从多个队列消费(如果客户端库支持)。 @zaq178miami 是的,但是这个答案是为了话题交换,并且根据问题的需要..!!! 我在上面提供了评论原因 - 该声明不适用于主题交换或任何其他方面。即使根据当前问题的条款(但这实际上取决于提问者使用哪个客户端库)。根据规则提供一般问题的答案,而不是具体问题,我投了反对票。如果我错了,请解释原因,我会尽力理解你的观点。我也是一个人,可能是错的,所以下面是我的答案,所以让社区来评判我们。我来这里不是为了分数,也不是为了我的简历中的线,而是分享我的知识并学习新的东西。对不起,如果伤害了你的感情。【参考方案2】:

对于典型的主题交换设置;你需要多少个队列?

这取决于您的应用程序需求。您可以从一个队列开始实现简单的 FIFO 堆栈,然后添加更多队列以消耗更细化的消息。

我的消费者可以只使用交换绑定,还是必须包含队列交互?

AMQP 交换的想法是获取已发布的消息并将它们放入一个或多个队列(甚至是其他交换或在某些条件下完全丢弃)。消费者仅适用于队列,而发布者仅适用于交换。

默认 Exchange 在将消息路由到与路由键相同的队列名称时可能存在一些误解,并且有时将其解释为发布到不正确的队列。

单条消息是否可以通过主题交换出现在 2 个消费者中(或者您是否需要为此进行扇出)?

我猜您是在谈论将一条消息复制到多个队列(虽然在某些错误情况下,您确实可能有多个消费者正在处理一条消息)。

如果是这样 - 当然。您可以为队列创建多个绑定以获取不同的消息。这是一个小例子:

让您使用三个不同的路由键customer.appA.createdcustomer.appB.created 和`customer.appC.created 将三个消息发布到主题交换。

您可以创建单独的队列来收集特定的消息,方法是使用确切的路由键 - customer.appA.createdcustomer.appB.created 等绑定队列,或者如您已经指出的,使用通配符路由键 customer.*.created 绑定队列。

要仅为 appA 和 appB 收集消息,您可以创建具有两个绑定 customer.appA.createdcustomer.appB.created 的队列,这样您将在一个队列中获得两种消息类型。

【讨论】:

以上是关于与 RabbitMQ 的主题交换歧义的主要内容,如果未能解决你的问题,请参考以下文章

Rabbitmq 主题模式

RabbitMQ之Fanout交换器模式开发

RabbitMQ事务和Confirm发送方消息确认

rabbitmq学习:rabbitmq之扇形交换机主题交换机

RabbitMQ:具有主题交换的持久消息

RabbitMQ学习 :主题交换机