原文来自 RabbitMQ 英文官网教程(1.Introduction),其示例代码采用了 .NET C# 语言。

RabbitMQ is a message broker: it accepts and forwards messages. You can think about it as a post office: when you put the mail that you want posting in a post box, you can be sure that Mr. Postman will eventually deliver the mail to your recipient. In this analogy, RabbitMQ is a post box, a post office and a postman.

RabbitMQ 是这样一个消息代理:它接收和转发消息。你可以把它想像成是一个邮局:当你把一份邮件投递到信箱时,你可以确信的是邮递员先生终究会把邮件递送给接收者。在这个比喻中,RabbitMQ 扮演了信箱、邮局以及邮递员这一系列角色。

The major difference between RabbitMQ and the post office is that it doesn't deal with paper, instead it accepts, stores and forwards binary blobs of data ‒ messages.

RabbitMQ与邮局最大的不同在于它并不处理纸质信件,取而代之的是它接收、储存以及转发二进制消息数据。

RabbitMQ, and messaging in general, uses some jargon.

RabbitMQ 以及消息传递,通常会使用到一些专业术语。

Producing means nothing more than sending. A program that sends messages is a producer :

生产者的含义无非就是发送,一个程序在发送消息时它就是生产者:

A queue is the name for a post box which lives inside RabbitMQ. Although messages flow through RabbitMQ and your applications, they can only be stored inside a queue. A queue is only bound by the host's memory & disk limits, it's essentially a large message buffer. Many producers can send messages that go to one queue, and many consumers can try to receive data from one queue. This is how we represent a queue:

队列实质上就是 RabbitMQ 内部的“信箱”,作为消息,尽管自 RabbitMQ 流经应用程序,但它最终只会存储于队列中。队列只会受限于主机内存和磁盘空间,本质上来讲它其实是一个庞大的消息缓存区。多个生产者可以发送消息到同一个队列,同时多个消费者也可以从同一个队列接收数据。下图是我们描绘的一个队列的模样:

Consuming has a similar meaning to receiving. A consumer is a program that mostly waits to receive messages:

同理,消费也有着类似接收的含义,消费者就是一个主要用来等待接收消息的程序:

Note that the producer, consumer, and broker do not have to reside on the same host; indeed in most applications they don't.

要注意的是,生产者、消费者,以及代理之间不必存在于同一台主机,事实上大部分应用程序也不会这么做。

"Hello World"

"起步"

In this part of the tutorial we'll write two programs in C#; a producer that sends a single message, and a consumer that receives messages and prints them out. We'll gloss over some of the detail in the .NET client API, concentrating on this very simple thing just to get started. It's a "Hello World" of messaging.

在教程的当前部分我们会编写两个 C# 程序。作为生产者会发送一条消息,同时消费者会接收消息并将其打印出来。我们会忽略 API 当中的一些细节,把精力集中在简单的事情上从而更好的起步。这是一个“Hello World”的消息。

In the diagram below, "P" is our producer and "C" is our consumer. The box in the middle is a queue - a message buffer that RabbitMQ keeps on behalf of the consumer.

在下图中,"P" 就是生产者,"C"就是消费者。中间的方形盒子就是队列,即 RabbitMQ 为消费者保留的消息缓冲区。

The .NET client library

.NET 客户端库

RabbitMQ speaks multiple protocols. This tutorial uses AMQP 0-9-1, which is an open, general-purpose protocol for messaging. There are a number of clients for RabbitMQ in many different languages. We'll use the .NET client provided by RabbitMQ.

RabbitMQ 支持多种协议,本教程使用的是 AMQP 0-9-1,它是公开的较为通用的消息协议。RabbitMQ 支持多种语言的客户端,在这里我们将使用 RabbitMQ 提供的 .NET 客户端。

The client supports .NET Core as well as .NET Framework 4.5.1+. This tutorial will use RabbitMQ .NET client 5.0 and .NET Core so you will ensure you have it installed and in your PATH.

RabbitMQ 提供的 .NET 客户端已支持 .NET Core 以及 .NET Framework 4.5.1+,本教程将会使用 RabbitMQ .NET client 5.0 和 .NET Core,所以你需要确认已安装成功。

You can also use the .NET Framework to complete this tutorial however the setup steps will be different.

你也可以使用 NET Framework 来完成本教程,然而其安装步骤会有所不同。

RabbitMQ .NET client 5.0 and later versions are distributed via nuget.

RabbitMQ .NET client 5.0 以及最新的版本是经由 Nuget 来发布的。

This tutorial assumes you are using powershell on Windows. On MacOS and Linux nearly any shell will work.

本教程假定你在 Windows 操作系统中会使用 PowerShell,可以放心的是,在 MacOS 和 Linux 中几乎所有的 Shell 环境都能正常运行。

Setup

安装

First lets verify that you have .NET Core toolchain in PATH:

首先让我们验证一下本地环境变量 PATH 中的 .NET Core 工具链:

dotnet --help

should produce a help message.

这时应当产生一个帮助消息。

Now let's generate two projects, one for the publisher and one for the consumer:

现在让我们来创建两个项目,一个是发布者,一个是消费者。

dotnet new console --name Send
mv Send/Program.cs Send/Send.cs
dotnet new console --name Receive
mv Receive/Program.cs Receive/Receive.cs

This will create two new directories named Send and Receive.

这一步将会创建两个文件夹,一个叫 Send,一个叫 Receive。

Then we add the client dependency.

紧接着我们来添加客户端依赖。

cd Send
dotnet add package RabbitMQ.Client
dotnet restore
cd ../Receive
dotnet add package RabbitMQ.Client
dotnet restore

Now we have the .NET project set up we can write some code.

好了,现在我们完成了 .NET 项目的安装,这样就可以写一些代码了。

Sending

发送

We'll call our message publisher (sender) Send.cs and our message consumer (receiver) Receive.cs. The publisher will connect to RabbitMQ, send a single message, then exit.

随后我们会调用消息发布者(发送)Send.cs,以及消息消费者(接收)Receive.cs。发布者会连接 RabbitMQ,并发送一条消息,然后退出。

In Send.cs, we need to use some namespaces:

在 Send.cs 中,我们需要引入一些命名空间:

using System;
using RabbitMQ.Client;
using System.Text;

Set up the class:

建立类文件:

class Send
{
public static void Main()
{
...
}
}

then we can create a connection to the server:

然后我们就可以创建一个通往服务器的连接。

class Send
{
public static void Main()
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
...
}
}
}
}

The connection abstracts the socket connection, and takes care of protocol version negotiation and authentication and so on for us. Here we connect to a broker on the local machine - hence the localhost. If we wanted to connect to a broker on a different machine we'd simply specify its name or IP address here.

该连接是抽象自套接字连接,为我们处理协议关于版本在协商与认证等方面的事宜。在这里,我们会连接到本地机器的一个代理,也就是 localhost。如果我们想连接到一台不同机器上的代理,只需简单地指定主机名或者 IP 地址。

Next we create a channel, which is where most of the API for getting things done resides.

接下来我们将创建一个信道,它在众多的 API 中负责着事项的正确处理。

To send, we must declare a queue for us to send to; then we can publish a message to the queue:

为了能顺利的发送,我们需要先定义一个队列,然后我们就可以发布消息了。

using System;
using RabbitMQ.Client;
using System.Text; class Send
{
public static void Main()
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using(var connection = factory.CreateConnection())
using(var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "hello",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null); string message = "Hello World!";
var body = Encoding.UTF8.GetBytes(message); channel.BasicPublish(exchange: "",
routingKey: "hello",
basicProperties: null,
body: body);
Console.WriteLine(" [x] Sent {0}", message);
} Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
}

Declaring a queue is idempotent - it will only be created if it doesn't exist already. The message content is a byte array, so you can encode whatever you like there.

声明队列的行为是幂等性的 - 即只有当一个队列不存在时才能被创建。

When the code above finishes running, the channel and the connection will be disposed.

当上述代码完成时,信道和连接将会被释放。

Here's the whole Send.cs class.

这里是完整的 Send.cs 类文件。

Sending doesn't work!
发送运行失败

If this is your first time using RabbitMQ and you don't see the "Sent" message then you may be left scratching your head wondering what could be wrong. Maybe the broker was started without enough free disk space (by default it needs at least 50 MB free) and is therefore refusing to accept messages. Check the broker logfile to confirm and reduce the limit if necessary. The configuration file documentation will show you how to set disk_free_limit.

如果这是你第一次使用 RabbitMQ,并且你没有收到“Sent”这一消息,这时你可能会抓耳挠腮,想知道是什么导致了错误。在这种情况下,有很大可能是因为代理(broker)在启动时没有足够的可用磁盘空间(默认至少需要 50M ),因此拒绝接收消息。检查代理(broker)日志文件(logfile),并进行确认以减少限制,通过查看配置文件文档,可以知晓如何设置 disk_free_limit。

Receiving

接收

That's it for our publisher. Our consumer is pushed messages from RabbitMQ, so unlike the publisher which publishes a single message, we'll keep it running to listen for messages and print them out.

以上是我们的发布者。我们的消费者已开始从 RabbitMQ 上被推送了消息,与发送一条消息的发布者有所不同的是,我们会让消费者持续地监听消息并将其打印出来。

The code (in Receive.cs) has almost the same using statements as Send:

在 Receive.cs 类文件中,using 区域的声明代码与 Send.cs 类文件近乎相同:

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;

Setting up is the same as the publisher; we open a connection and a channel, and declare the queue from which we're going to consume. Note this matches up with the queue that send publishes to.

与发布者的设置一样,我们打开一个连接和信道,并且声明好队列以作好消费的准备。需要注意的是,该队列与发布者所发送消息的队列是相匹配的(即基于同一个队列)。

class Receive
{
public static void Main()
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "hello",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
...
}
}
}
}

Note that we declare the queue here, as well. Because we might start the consumer before the publisher, we want to make sure the queue exists before we try to consume messages from it.

可以看到我们在消费者这里又声明了一次队列(QueueDeclare),在实践中,我们很可能是先启动消费者,后启动发布者。所以重复的声明代码,是当我们尝试从队列中消费消息时,确保队列总是已存在的。

We're about to tell the server to deliver us the messages from the queue. Since it will push us messages asynchronously, we provide a callback. That is what EventingBasicConsumer.Received event handler does.

我们即将告知服务器从队列中向我们递送消息,因为该动作是基于异步的,所以我们需要提供回调,这便是 EventingBasicConsumer.Received 事件处理方法所要做的。

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text; class Receive
{
public static void Main()
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using(var connection = factory.CreateConnection())
using(var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "hello",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null); var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] Received {0}", message);
};
channel.BasicConsume(queue: "hello",
autoAck: true,
consumer: consumer); Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
}
}

Here's the whole Receive.cs class.

这里是完整的 Receive.cs 类文件

Putting It All Together

融合一起

Open two terminals.

打开两个终端。

Run the consumer:

运行消费者:

cd Receive
dotnet run

Then run the producer:

紧接着运行生产者:

cd Send
dotnet run

The consumer will print the message it gets from the publisher via RabbitMQ. The consumer will keep running, waiting for messages (Use Ctrl-C to stop it), so try running the publisher from another terminal.

消费者会经由 RabbitMQ 打印出那些来自发布者的消息。消费者会持续运行,以等待消息(使用 Ctrl-C 来终止运行),如此,我们可以尝试从其他终端来运行发布者(重复运行多个生产者实例程序)。

《RabbitMQ Tutorial》第 1 章 简介的更多相关文章

  1. 《JavaScript模式》第1章 简介

    @by Ruth92(转载请注明出处) 第1章 简介 模式 模式:是指一个通用问题的解决方案. 设计模式 编码模式 反模式:常见的.引发问题比解决的问题更多的一种方法. JavaScript 基本概念 ...

  2. AngularJS——第1章 简介

    第1章 简介 由谷歌公司开发维护的前端MVC框架,克服了HTML在构建应用上的诸多不足,降低了开发成本,提高了效率. 一个框架 以数据和逻辑作为驱动 AngularJS核心特性:模块化,双数据绑定,语 ...

  3. hibernate课程 初探单表映射2-1 hibernate进阶 本章简介

    本章简介,主要讲5大块的内容 1 hibernate.cfg.xml的配置 2 session 的简介 3 transaction的简介 4 session的详解 5 对象关系映射常用配置

  4. RabbitMQ入门教程(二):简介和基本概念

    原文:RabbitMQ入门教程(二):简介和基本概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn ...

  5. 读书笔记 - javascript 高级程序设计 - 第一章 简介

      第一章 简介   诞生时间 1995 最初用途 客服端验证 第一版标准 注意是标准 1997年 Ecma-262  一个完整的js实现由三部分组成 ECMAScript DOM 文档对象模型 BO ...

  6. Unity 游戏框架搭建 2019 (九~十二) 第一章小结&第二章简介&第八个示例

    第一章小结 为了强化教程的重点,会在合适的时候进行总结与快速复习. 第二章 简介 在第一章我们做了知识库的准备,从而让我们更高效地收集示例. 在第二章,我们就用准备好的导出工具试着收集几个示例,这些示 ...

  7. Unity 游戏框架搭建 2019 (三十九、四十一) 第四章 简介&方法的结构重复问题&泛型:结构复用利器

    第四章 简介 方法的结构重复问题 我们在上一篇正式整理完毕,从这一篇开始,我们要再次进入学习收集示例阶段了. 那么我们学什么呢?当然是学习设计工具,也就是在上篇中提到的关键知识点.这些关键知识点,大部 ...

  8. Unity 游戏框架搭建 2019 (五十二~五十四) 什么是库?&第四章总结&第五章简介

    在上一篇,我们对框架和架构进行了一点探讨.我们在这一篇再接着探讨. 什么是库呢? 来自同一位大神的解释: 库, 插到 既有 架构 中, 补充 特定 功能. 很形象,库就是搞这个的.我们的库最初存在的目 ...

  9. 《RabbitMQ Tutorial》译文 第 1 章 简介

    原文来自 RabbitMQ 英文官网的教程(1.Introduction),其示例代码采用了 .NET C# 语言. RabbitMQ is a message broker: it accepts ...

随机推荐

  1. 【NOIP模拟】LCS及方案数(DP)

    Description 对于一个序列

  2. LINUX 笔记-ps命令

    使用该命令能确定有哪些进程正在运行和运行的状态.进程是否结束.进程有没有僵死.哪些进程占用了过多的资源等等 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME ...

  3. C语言 数组名不是指针

    今天上计算机系统课的时候老师讲到了C中的聚合类型的数据结构.在解释数组名的时候说"数组名是一个指针,指向该数组的第一个元素",附上ppt(第二行): 我觉得这是不正确的,是一个常见 ...

  4. Java规范推荐

    Java规范推荐 推荐:http://blog.csdn.net/tristansmile/article/details/7989670 命名规范 项目名:全部小写 Package 的命名:应该都是 ...

  5. LeetCode 79. Word Search(单词搜索)

    Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from l ...

  6. css左侧固定宽度,右侧自适应的几种实现方法

    左侧固定,右侧自适应或者右侧固定在,左侧自适应是一样的.这种布局很常见,而且面试过程中也经常会问到,这里我总结的方法一共有5种.要实现这种布局,也算比较简单.我们先给出html结构: <div ...

  7. System.getProperty参数大全

    System.getProperty()参数大全 #java.version                                    Java Runtime Environment v ...

  8. centos 6.9安装zabbix 3.0

    Linux下常用的系统监控软件有Nagios.Cacti.Zabbix.Monit等,这些开源的软件,可以帮助我们更好的管理机器,在第一时间内发现,并警告系统维护人员. 今天开始研究下Zabbix,使 ...

  9. Group(), Groups(),& Groupdict()

    group() 返回一个或多个匹配的字串.如果只有一个参数,结果只有单个字符串:如果有多个参数,结果是一个元组,元组里每一项对应一个参数.没有参数,group1默认是0(整个匹配串被返回).如果gro ...

  10. 启动Apache出现问题:一直停留在启动界面

    问题描述:  由于需要php_curl模块,因此直接在php.ini文件将前面的分号去掉  ,但是重启Apache时出现:一直停留在启动界面,Apache无法正常启动,查看错误日志,显示如下: 解决方 ...