簡介
RabbitMQ是一個message broker(消息中間件):它接受和轉發消息。你可以把它想象成一個郵局:當你把你想要發佈的郵件放在一個郵筒裏時,你可以確定郵遞員最終會把郵件交給你的收件人。在這個類比中,RabbitMQ是一個郵筒、一個郵局和一個郵遞員。
RabbitMQ和郵局之間的主要區別在於,它不處理紙張,而是接受、存儲和轉發二進制數據消息。
RabbitMQ和消息傳遞通常使用一些術語。
Producing
的思就是發送。一個發送消息的程序是一個生產者:
Queue
(隊列)是位於RabbitMQ內的一個郵筒的名稱。儘管消息通過RabbitMQ和您的應用程序流動,但它們只能存儲在隊列中。隊列只受主機的內存和磁盤限制的限制,它本質上是一個大的消息緩衝區。許多生產者可以發送到一個隊列的消息,許多消費者可以嘗試從一個隊列接收數據。這就是我們如何表示隊列的方式:
Consuming
(消費者)對接收也有類似的含義。消費者是一個主要等待接收消息的程序:
請注意,生產者(Producer)、消費者(consumer)和中間件(borker)不需要駐留在同一個主機上;事實上,在大多數應用中,它們都沒有。
“Hello World”
(using the .NET/C# Client)
在本教程的這一部分,我們將在C#中編寫兩個程序;一個發送單一消息的生產者,以及一個接收消息並將其打印出來的消費者。我們將對.NET客戶端API中的一些細節進行註釋,將重點放在這個非常簡單的事情上,以便開始。這是一個信息傳遞的“Hello World”。
在下面的圖表中,“P”是我們的生產者,而“C”是我們的消費者。中間的盒子是一個隊列——RabbitMQ代表消費者保存的消息緩衝區。
The .NET client library
RabbitMQ講多種協議。本教程使用AMQP 0-9-1,這是一種開放的、通用的消息傳遞協議。在許多不同的語言中,RabbitMQ有許多客戶端。我們將使用RabbitMQ提供的`.NET Client。
客戶端支持.Net Core Net Framework4.5.1+ 本教程將使用RabbitMQ.NET客戶端5.0和.NET Core,這樣您就可以確保安裝並在您的路徑中安裝了它。
您還可以使用.NET框架來完成本教程,但是設置步驟將有所不同。
RabbitMQ。NET客戶端5.0和以後的版本是通過nuget分發的。
本教程假設您在Windows上使用powershell。在MacOS和Linux上,幾乎任何shell都可以工作。
安裝
首先,讓我們驗證您在PATH中有。NET核心工具鏈:
dotnet --help
應該提供一個幫助信息。
現在,讓我們生成兩個項目,一個用於publisher,一個用於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
這將創建兩個名爲Send和Receive的新目錄。
然後我們添加客戶端依賴項。
cd Send
dotnet add package RabbitMQ.Client
dotnet restore
cd ../Receive
dotnet add package RabbitMQ.Client
dotnet restore
現在我們已經建立了。NET項目,我們可以編寫一些代碼。
Sending (發送)
using System;
using RabbitMQ.Client;
using System.Text;
連接抽象了套接字連接,並負責協議版本的協商和認證,等等。在這裏,我們連接到本地機器上的代理——因此是localhost。如果我們想要連接到另一臺機器上的代理,我們只需在這裏指定它的名稱或IP地址。
接下來,我們創建一個通道,這是大多數用於完成任務的API所在。
爲了發送,我們必須聲明一個隊列供我們發送;然後我們可以向隊列發佈一條消息:
public 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",
exclusive: false,
autoDelete: false,
arguments: null);
string message = "Hello World!";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "",
basicProperties: null,
body: body);
Console.WriteLine(" [x] Sent {0}", message);
}
Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
}
Receiving(接收者)
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;
設置與publisher是一樣的;我們打開一個連接和一個通道,並聲明我們將要消費的隊列。注意,這與發送發佈到的隊列相匹配。
注意,我們也在這裏聲明隊列。因爲我們可能會在publisher之前啓動消費者,所以在嘗試使用它之前,我們希望確保隊列的存在。
我們將告訴服務器從隊列中傳遞消息。因爲它會異步地推送我們的消息,所以我們提供了一個回調。這就是EventingBasicConsumer。收到的事件處理程序。
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();
}
}
}