1. 程式人生 > >[譯]RabbitMQ教程C#版 - "Hello World"

[譯]RabbitMQ教程C#版 - "Hello World"

原文: [譯]RabbitMQ教程C#版 - "Hello World"

先決條件
本教程假定 RabbitMQ 已經安裝,並執行在localhost標準埠(5672)。如果你使用不同的主機、埠或證書,則需要調整連線設定。

從哪裡獲得幫助
如果您在閱讀本教程時遇到困難,可以通過郵件列表 聯絡我們

介紹

RabbitMQ 是一個訊息中介軟體:它接收並轉發訊息。您可以把它想象為一個郵局:當您把需要寄出的郵件投遞到郵箱,郵差最終會把郵件送給您的收件人。在這個比喻中,RabbitMQ 就是一個郵箱,也可以理解成郵局和郵遞員。

RabbitMQ 和郵局的主要區別在於它不處理紙張,而是接收、儲存和轉發二進位制資料塊 - 訊息

RabbitMQ 和訊息傳遞通常使用一些術語。

生產 的意思無非就是傳送。傳送訊息的程式就是一個 生產者

Producer

佇列 就是 RabbitMQ 內部“郵箱”的名稱。雖然訊息流經 RabbitMQ 和您的應用程式,但它們只能儲存在 佇列 中。佇列 只受主機的記憶體和磁碟的限制,它本質上就是一個很大的訊息緩衝區。多個 生產者 可以傳送訊息到一個佇列,並且多個 消費者 可以嘗試從一個 佇列 接收資料。這就是我們代表隊列的方式:

Queue

消費 與接收有相似的含義,等待接收訊息的程式就是一個 消費者

Consumer

注意:生產者、消費者和中介軟體不是必須部署在同一主機上,實際上在大多數應用程式中它們也不是這樣的。

"Hello World"

使用 .NET / C#Client

在教程的這一部分,我們將用 C# 編寫兩個程式:一個傳送單條訊息的生產者,以及接收訊息並將其打印出來的消費者。我們將忽略 .NET 客戶端 API 中的一些細節,專注於更簡單的開始。這是一個訊息傳遞的“Hello World”。

在下圖中,P是我們的生產者,C是我們的消費者。中間的盒子是佇列 - RabbitMQ 代表消費者儲存的訊息緩衝區。

.NET 客戶端庫

RabbitMQ 支援多種協議,本教程使用AMQP 0-9-1,它是一種開放的、通用的訊息傳遞協議。RabbitMQ 提供了一些針對不同 語言環境

的客戶端,我們將使用 RabbitMQ 提供的 .NET 客戶端。

客戶端支援 .NET Core 以及 .NET Framework 4.5.1+。本教程將使用 .NET Core,因此您需要確保客戶端已 安裝 並且路徑新增到PATH系統變數。

您也可以使用 .NET Framework 來完成本教程,但設定步驟會有所不同。

RabbitMQ .NET 客戶端 5.0 及更高版本通過 nuget 釋出。

本教程假定您在 Windows 上使用 PowerShell。在 MacOS 和 Linux 上,幾乎所有 shell 也都可以正常工作。

安裝

首先讓我們驗證您在PATH系統變數是否有 .NET Core 工具鏈:

dotnet --help

應該產生幫助資訊。

現在,讓我們生成兩個專案,一個用於釋出者,另一個用於消費者:

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

這將建立兩個名為SendReceive的新目錄。

然後,我們新增客戶端依賴項。

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

我們已經建立了 .NET 專案,現在我們可以編寫一些程式碼。

傳送

我們將呼叫我們的訊息釋出者(傳送者)Send.cs和我們的訊息消費者(接收者)Receive.cs。釋出者將連線到 RabbitMQ,傳送一條訊息,然後退出。

Send.cs 中,我們需要使用一些名稱空間:

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

設定類:

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

然後,我們可以建立一個連線,連線到伺服器:

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

該連線抽象了套接字連線,併為我們處理協議版本的協商和身份驗證等。在這裡,我們連線的是本地機器上的代理, 因此是localhost。如果我們想連線到其他機器上的代理,我們只需在此指定其名稱或 IP 地址。

接下來,我們建立一個通道,該 API 的主要功能是把獲得資訊儲存起來。

想要傳送訊息,我們必須為需要傳送的訊息宣告一個佇列,然後我們就可以把訊息釋出到佇列中:

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();
    }
}

宣告佇列是 冪等 的 - 只有當它不存在時才會被建立。訊息內容是一個位元組陣列,所以您可以用喜歡的任意方式編碼。

當上面的程式碼完成執行時,通道和連線將被釋放。這就是我們的釋出者。

Send.cs 原始碼)

傳送不起作用!

如果這是您第一次使用 RabbitMQ,並且您沒有看到“已傳送”訊息,那麼您可能會撓著頭想知道錯誤出在什麼地方。也許是代理程式啟動時沒有足夠的可用磁碟空間(預設情況下,它至少需要50 MB空閒空間),因此拒絕接收訊息。
必要時檢查代理程式日誌檔案來確認和減少限制。配置檔案 文件 將告訴您如何設定disk_free_limit

接收

至於消費者,它是把訊息從 RabbitMQ 拉取過來。因此,與釋出訊息的釋出者不同,我們會保持消費者持續不斷地執行,監聽訊息並將其打印出來。

程式碼(在 Receive.cs 中)具有與Send差不多一樣的using宣告:

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

設定與釋出者相同;我們開啟一個連線和一個通道,並宣告我們將要使用的佇列。請注意,這需要與Send釋出到的佇列相匹配。

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);
                ...
            }
        }
    }
}

請注意,我們在這裡也聲明瞭佇列。因為我們可能會在釋出者之前啟動消費者,所以我們希望在我們嘗試從它中消費訊息之前確保佇列已存在。

我們即將告訴伺服器將佇列中的訊息傳遞給我們。由於它會非同步推送訊息,因此我們提供了一個回撥。這就是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();
        }
    }
}

Receive.cs 原始碼)

組合在一起

開啟兩個終端。

執行消費者:

cd Receive
dotnet run

執行生產者:

cd Send
dotnet run

消費者將列印它通過 RabbitMQ 從釋出者處獲得的訊息。消費者將繼續執行、等待新訊息(按Ctrl-C將其停止),可以嘗試從開啟另一個終端執行釋出者。

接下來可以跳轉到 教程[2],構建一個簡單的工作佇列。

寫在最後

本文翻譯自 RabbitMQ 官方教程 C# 版本。如本文介紹內容與官方有所出入,請以官方最新內容為準。水平有限,翻譯的不好請見諒,如有翻譯錯誤還請指正。