《RabbitMQ Tutorial》译文 第 3 章 发布和订阅
原文来自 RabbitMQ 英文官网的教程(3.Publish and Subscribe),其示例代码采用了 .NET C# 语言。
In the previous tutorial we created a work queue. The assumption behind a work queue is that each task is delivered to exactly one worker. In this part we'll do something completely different -- we'll deliver a message to multiple consumers. This pattern is known as "publish/subscribe".
在之前的教程中我们创建了一个工作队列,其背后的设想便是每一个任务恰好地递送给一个工作单元。在本教程中,我们的做法将完全不同 -- 即递送消息给多个消费者,这个模式被称作“发布/订阅”。
To illustrate the pattern, we're going to build a simple logging system. It will consist of two programs -- the first will emit log messages and the second will receive and print them.
为了说明这个模式,我们将要构建一个简单日志系统。它将由两个程序组成 -- 第一个将会发送日志消息,而第二个将会接收并打印它们。
In our logging system every running copy of the receiver program will get the messages. That way we'll be able to run one receiver and direct the logs to disk; and at the same time we'll be able to run another receiver and see the logs on the screen.
在我们的日志系统中,每一个正在运行的接收程序副本都将获得消息。如此,我们将运行一个接收者来将日志写入磁盘,与此同时再运行另一个接收者,这样可以在屏幕上查看日志。
Essentially, published log messages are going to be broadcast to all the receivers.
本质上来讲,已发布的日志消息将会广播给所有的接收者。
Exchanges 交换机In previous parts of the tutorial we sent and received messages to and from a queue. Now it's time to introduce the full messaging model in Rabbit.
在本教程的之前部分,我们从队列中发送和接收消息,现在是时候来介绍 Rabbit 中完整的消息模型了。
Let's quickly go over what we covered in the previous tutorials:
让我们快速温习一下之前教程中所包括的内容:
The core idea in the messaging model in RabbitMQ is that the producer never sends any messages directly to a queue. Actually, quite often the producer doesn't even know if a message will be delivered to any queue at all.
在 RabbitMQ 中,消息模型的核心理念是生产者永远不会把任何消息直接发送到队列。事实上,通常生产者甚至不知道消息是否会被递送到任何队列。
Instead, the producer can only send messages to an exchange. An exchange is a very simple thing. On one side it receives messages from producers and the other side it pushes them to queues. The exchange must know exactly what to do with a message it receives. Should it be appended to a particular queue? Should it be appended to many queues? Or should it get discarded. The rules for that are defined by the exchange type.
取而代之的是,生产者只能发送消息给一个交换机。交换机很简单,一方面它从生产者接收消息,另一方面它又把消息推送到队列。但是交换机必须明确知道对它所接收到的消息该做什么。(比如)需要将消息追加到指定队列?还是追加到多个队列?还是要丢弃?这些规则都是在交换机类型中定义。
There are a few exchange types available: direct, topic, headers and fanout. We'll focus on the last one -- the fanout. Let's create an exchange of this type, and call it logs:
目前有若干交换机类型可用:direct、topic、headers 以及 fanout。我们将以最后一个为重点 -- fanout,让我们创建一个该类型的交换机,并将其叫作“logs”:
channel.ExchangeDeclare("logs", "fanout");The fanout exchange is very simple. As you can probably guess from the name, it just broadcasts all the messages it receives to all the queues it knows. And that's exactly what we need for our logger.
fanout 型交换机非常简单,从它的名称你可能猜出,它会广播所有已接收到的消息给所有已知的队列,这正好是我们的日志系统所需要的。
Listing exchanges 列举出交换机To list the exchanges on the server you can run the ever useful rabbitmqctl:
为了列举出服务端的交换机,你可以运行此前非常有用的 rabbitmqctl 命令:
sudo rabbitmqctl list_exchangesIn this list there will be some amq.* exchanges and the default (unnamed) exchange. These are created by default, but it is unlikely you'll need to use them at the moment.
在这个列表中有一些 amq.* 和默认的(未命名)交换机,这些都是默认创建的,但此时你不太可能需要用到它们。
The default exchange 默认的交换机In previous parts of the tutorial we knew nothing about exchanges, but still were able to send messages to queues. That was possible because we were using a default exchange, which we identify by the empty string ("").
在教程的之前部分我们对交换机还一无所知,但这并不妨碍我们能够发送消息到队列中,这之所以成为可能,是因为我们使用了基于空字符串来标识的默认交换机。
Recall how we published a message before:
回忆一下以前我们是如何发布消息的:
var message = GetMessage(args); var body = Encoding.UTF8.GetBytes(message); channel.BasicPublish(exchange: "", routingKey: "hello", basicProperties: null, body: body);