先決條件
本教程假定 RabbitMQ 已經安裝,並運行在localhost
標準端口(5672)。若是你使用不一樣的主機、端口或證書,則須要調整鏈接設置。html從哪裏得到幫助
若是您在閱讀本教程時遇到困難,能夠經過郵件列表 聯繫咱們。git
RabbitMQ 是一個消息中間件:它接收並轉發消息。您能夠把它想象爲一個郵局:當您把須要寄出的郵件投遞到郵箱,郵差最終會把郵件送給您的收件人。在這個比喻中,RabbitMQ 就是一個郵箱,也能夠理解成郵局和郵遞員。github
RabbitMQ 和郵局的主要區別在於它不處理紙張,而是接收、存儲和轉發二進制數據塊 - 消息。shell
RabbitMQ 和消息傳遞一般使用一些術語。windows
生產 的意思無非就是發送。發送消息的程序就是一個 生產者:數組
隊列 就是 RabbitMQ 內部「郵箱」的名稱。雖然消息流經 RabbitMQ 和您的應用程序,但它們只能存儲在 隊列 中。隊列 只受主機的內存和磁盤的限制,它本質上就是一個很大的消息緩衝區。多個 生產者 能夠發送消息到一個隊列,而且多個 消費者 能夠嘗試從一個 隊列 接收數據。這就是咱們表明隊列的方式:服務器
消費 與接收有類似的含義,等待接收消息的程序就是一個 消費者:異步
注意:生產者、消費者和中間件不是必須部署在同一主機上,實際上在大多數應用程序中它們也不是這樣的。工具
使用 .NET / C#Clientgoogle
在教程的這一部分,咱們將用 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
這將建立兩個名爲Send
和Receive
的新目錄。
而後,咱們添加客戶端依賴項。
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# 版本。如本文介紹內容與官方有所出入,請以官方最新內容爲準。水平有限,翻譯的很差請見諒,若有翻譯錯誤還請指正。