RabbitMQ:如何将任务队列和扇出/路由/主题模型结合起来?

use*_*018 3 rabbitmq

我的环境中有一个生产者和多个消费者。
生产者创建 2 种类型的消息:

  1. 一条消息只需要由一个消费者处理(任何消费者都可以)。
  2. 需要由所有消费者处理的消息。

如何实施?
对于消息类型 1,工作队列是合适的模型。
对于消息类型 2,扇出/直接/路由/主题是合适的。
但我该如何将它们结合起来呢?

小智 5

RabbitMQ 非常灵活,您可以有许多不同的交换和队列设计解决方案来满足您的要求。

但是,首先我们需要了解队列和消费者之间的关系和基本规则:

  • 如果您希望某个消息类型仅由所有消费者中的一个消费,正如您所说,您需要一个工作队列,所有消费者都应该订阅它。
  • 如果您希望每个消费者都消费某个消息类型,则需要为每个消费者拥有队列,并且每个消费者仅订阅自己的队列。

根据上面的理解就清楚了队列的数量。剩下的事情是如何将消息路由到这些队列。会有很多解决方案。以下仅是一些示例。

一种可行的解决方案是创建两个交换器,每个交换器对应一种消息类型。

| message type | exchange name | exchange type | bound queues      |
|------------------------------------------------------------------|
| type_1       | exchange1     | fanout        | shared_queue      |
| type_2       | exchange2     | fanout        | queue1,queue2,... |
Run Code Online (Sandbox Code Playgroud)

另一种可行的解决方案是,如果您只想使用一个交换器来发布两种消息类型,请使用“直接”交换类型:

| routing_key | binding_key | bound queues      |
|-----------------------------------------------|
| type_1      | type_1      | shared_queue      |
| type_2      | type_2      | queue1,queue2,... |
Run Code Online (Sandbox Code Playgroud)

一个交换器可以使用相同的绑定密钥绑定多个队列。因此,当使用发布路由键“type_1”发布类型1的消息时,只有shared_queue会收到该消息;当使用发布路由键“type_2”发布消息类型2时,所有队列1,队列2,...都会收到该消息。

如果您有更多消息类型并且不想使用相同的路由键,则为每个消息使用不同的绑定键可能并不适合实际情况。如果是这样,您可能想使用“topic”交换类型:

| routing_key | binding_key | bound queues      |
|-----------------------------------------------|
| type_1.1    | type_1.*    | shared_queue      |
| type_2.2    | type_2.*    | queue1,queue2,... |
Run Code Online (Sandbox Code Playgroud)