仅将消息传递给绑定到 RabbiqMQ 直接交换中的路由键的一个队列

Deliver message to only one queue bound to a routing key in RabbiqMQ Direct exchange

我是 RabbitMQ 的新手,这让我很困惑。我已经设置了一个直接交换器,不同的队列在这个交换器上订阅了不同的路由键。我想要的是,如果一条消息使用一个路由键发布,则它只会从一个订阅者处使用,无论有多少队列订阅了该路由键。

当前情景:

交换(类型:直接)

-QueueA1  (receives message A from exchange with routing key of "TypeA")
-QueueA2  (also receive message A from exchange with routing key of "TypeA")
-QueueB  (doesn't receive message A because it subscribes to key "TypeB")

期望:

-QueueA1  (receives message A from exchange with routing key of "TypeA")
-QueueA2  (doesn't receive message A because it's already consumed by QueueA1)
-QueueB  (doesn't receive message A because it subscribes to key "TypeB")

我需要使用不同的交易所吗?如何实现所需的场景?

您可以通过使用单个 QueueA 和多个订阅此队列的消费者来实现您想要的:

Direct exchange
|
|-- ["TypeA"]--> QueueA
|                |-- Consumer A1
|                `-- Consumer A2
|
`-- ["TypeB"]--> QueueB

在这种情况下,在 QueueA 上排队的消息将只传递给一个消费者。然而,接收消息的消费者是未定义的:他们以循环方式被挑选。

w/ RabbitMQ,在给定交换中匹配的所有路由键,将有一份传递到指定队列的消息副本。

因此,在您的场景中,您将始终让 QueueA1 和 QueueA2 接收 TypeA 的消息。这就是路由键的工作原理。没有办法解决这个问题,使用单个交换器。

如果您需要 QueueA1 和 QueueA2 接收不同的消息,那么您可以:

  • 需要使用不同的路由键来绑定队列,或者
  • 需要使用不同的交易所

关于 Jean-Sebastient 的建议...

此方案将允许消费者 A1 消费者 A2 处理相关消息,但通过让他们都订阅同一队列来实现。

如果您试图确保有 1 个消费者收到消息,那么这就是您想要做的。但是,如果您需要两个队列并且需要确保只有一个队列接收消息,那么您需要使用我建议的其他选项之一。

最后,如果您希望保证一条消息仅被处理一次,none 这些选项都可以。

从表面上看,大部分时间都是这样。但是在某些情况下会出现问题,并且您会有多个队列或消费者处理同一消息。

要处理这种情况,您需要在消息处理中查看 "idempotence"。这通常使用数据库和一个 ID 来处理,表明它已经被处理过,但还有其他解决方案。