在前面的文章中,我们都称将消息发送到队列中,这是一个不准确的表述。在RabbitMQ中,消息传递模型的核心思想是:生产者从不直接向队列发送任何消息。事实上,生产者甚至都不知道消息会被投递到哪个队列中。一个基本的消息传递模型图如下所示:

  • P:生产者。发送消息的角色,将消息发送给X(交换机),在发送时可以附加路由键RoutingKey参数。
  • X:交换机。负责转发消息,不具备消息存储的能力,如果没有任何队列和交换机绑定,或者没有符合路由规则的队列,那么消息会丢失。
  • Queue:队列。接收消息,缓存消息。
  • C:消费者。一直等待消息的到来。

交换机(Exchange

生产者只能将消息发送到交换机(Exchange)。交换机的工作内容非常简单。一方面它接收来自生产者的消息,另一方面它将消息推入队列。交换机必须确切地知道如何处理收到的消息,是投递到一个特定队列还是投递给多个队列又或者是丢弃。这些处理规则由交换机的类型来决定。

交换机的类型

有以下四种可用的交换机类型:

  • direct:直接类型
  • topic:主题类型
  • headers:标题类型
  • fanout:扇出类型

默认交换机

在之前的示例中,我们没有定义任何交换机但仍然能够将消息发送到队列中,原因是因为我们使用了默认交换机,通过设置channel.basicPublish方法的第一个参数为空字符串“”来表示。默认交换机的类型是direct直接类型。

对应控制台的(AMQP default)交换机:

image-20220421200718741

路由键(RoutingKey

消息被发送到交换机时可以提供一个RoutingKey路由键参数,路由键将与绑定键配合使用,其具体含义取决于交换机的类型。

临时队列

在之前的示例中,我们使用的都是具有特定名称的队列(例如helloack_queue等)。一般情况下队列名称都很重要,我们需要指定消费者去消费哪个队列的消息。但某些情况下我们可能希望每次连接RabbitMQ时都获得一个全新的空队列,每次断开连接时,队列又会被自动删除。这样的队列我们就称之为临时队列。

RabbitMQ客户端支持我们快速创建临时队列:

1
2
// 临时队列:具有随机生成名称的非持久、独占、自动删除的队列。
String queueName = channel.queueDeclare().getQueue();

当我们不向queueDeclare()方法提供任何参数时,RabbitMQ就会创建一个具有随机名称的、非持久化的、独占的、自动删除的队列。生成的随机名称类似于字符串amq.gen-SddofZXWVdBfLQtb3Vde5g

绑定(Binding

告诉交换机向哪些队列发送消息。交换机和队列之间的这种关系称为绑定。

bindings

绑定键(RoutingKey

交换机和队列之间的绑定可以提供额外的RoutingKey参数。为了避免与消息发送到交换机时的路由键混淆,我们将其称为绑定键。交换机会根据不同的交换机类型以及消息的路由键和队列的绑定键共同决定将消息投递到哪个队列。