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 i ...
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.
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.
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 來終止運行),如此,我們可以嘗試從其他終端來運行發佈者(重覆運行多個生產者實常式序)。
【轉:http://www.cnblogs.com/ramantic/p/7993047.html】
歡迎大家關註我都我的微信 公眾號,公眾號漲粉絲人數,就是你們對我的喜愛程度!