引言
在前面我们学习了RabbitMQ简介,安装及简单使用:docker-compose安装rabbitmq及简单使用Hello World
还有队列的简单使用,循环调度,消息确认,消息持久化,公平分发:队列使用
在之前的两个教程中,我们创建了一个工作队列。工作队列背后的假设是每个消息任务只传递给一个工人。在这一部分中,我们将做一些完全不同的事情——我们将向多个消费者传递同一个消息。这就是所谓的“订阅/发布模式”
。
为了说明这种模式,我们将构建一个简单的日志系统。它将由两个程序组成——第一个程序将发出日志消息,第二个程序将接收并打印它们。
在我们的日志系统中,每一个运行的接收器程序副本都会收到消息。这样,我们就可以运行一个接收器并将日志定向到磁盘;同时,我们还可以运行另一个接收器并在屏幕上查看日志。
本质上,已发布的日志消息将被广播到所有接收者。
Exchanges(交换器)
RabbitMQ消息传递模型中的核心思想是生产者从不将任何消息直接发送到队列。实际上,生产者经常甚至根本不知道是否将消息传递到任何队列。
相反,生产者只能将消息发送到交换器
。交换器是非常简单的东西。一方面,它接收来自生产者的消息,另一方面,将它们推入队列。交换器必须确切知道如何处理接收到的消息。它应该被附加到特定的队列吗?还是应该将其附加到许多队列中?或者它应该被丢弃。这些规则由交换器的类型定义。
有几种交换器类型可用:direct
, topic
, headers
和 fanout
。我们将集中讨论最后一个——fanout
。让我们创建一个这种类型的交换器,并给它起个名字叫logs:
err = ch.ExchangeDeclare(
"logs", // name
"fanout", // type
true, // durable 开启持久化
false, // auto-deleted
false, // internal
false, // no-wait
nil, // arguments
)
fanout(扇出)
交换器非常简单。正如你可能从名称中猜测的那样,它只是将接收到的所有消息广播到它知道的所有队列中。而这正是我们记录器所需要的。
Exchanges List
要列出服务器上的交换器,你可以执行有用的rabbitmqctl命令:
rabbitmqctl list_exchanges
结果如下:
在此列表中,将有一些amq.*
交换器和一个默认的(未命名)交换器。这些是默认创建的,但是你现在不太可能需要使用它们。
默认交换器
在前面的两个教程中,我们还不知道交换器的存在,但仍然能够将消息发送到队列。之所以能这样做,是因为我们使用的是默认交换器,该交换器由空字符串(""
)标识。
回想一下我们之前是怎么发布消息的:
err = ch.Publish(
"", // exchange
q.Name, // routing key
false, // mandatory
false, // immediate
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(body),
})
在这里,我们使用默认或无名称的交换器:消息将以route_key
参数指定的名称路由到队列(如果存在)。
现在,我们可以改为发布到我们的命名交换器:
err = ch.ExchangeDeclare(
"logs", // 使用命名的交换器
"fanout", // 交换器类型
true, // durable
false, // auto-deleted
false, // internal
false, // no-wait
nil, // arguments
)
if