標籤:oca 根據 表示 vhost == 基於 通道 use uid
今天這篇博文是我翻譯的RabbitMQ的最後一篇文章了,介紹一下RabbitMQ的C#開發的介面。好了,言歸正傳吧。
Net/C# 用戶端 API簡介
1、主要的命名空間,介面和類
定義核心的API的介面和類被定義在RabbitMQ.Client這個命名空間下面:
所以要想使用RabbitMQ的功能,需要以下代碼
using RabbitMQ.Client;
【1】、核心API的介面和類如下:
IModel:表示一個符合AMQP 0-9-1 協議的通道,並且提供了很多的操作方法
IConnection:表示一個符合AMQP 0-9-1協議的連線物件,使用者和RabbitMQ 服務端的串連
ConnectionFactory:可以建立一個IConnection對象的執行個體。
IBasicConsumer:表示一個訊息的消費者,或者是使用者。
【2】、其他有用的介面和類包含如下:
DefaultBasicConsumer:通常用作消費者的基類,如果要編寫自己的消費者程式,可以從該類繼承。
【3】、除RabbitMQ.Client之外的公用命名空間包括:
RabbitMQ.Client.Events:作為用戶端庫一部分的各種事件和事件處理常式。
包括EventingBasicConsumer,一個基於C#事件處理常式構建的消費者實現。
RabbitMQ.Client.Exceptions: 對使用者可見的一些異常對象。
所有其他命名空間都保留用於庫的私人實現細節,儘管私人命名空間的成員通常可以使用該庫的應用程式使用,以便允許開發人員實現其在庫實現中發現的故障或設計錯誤的解決方案。 應用程式不能依賴於在庫的版本中保持穩定的私人命名空間中出現的任何類,介面,成員變數等。
2、建立到代理的串連
要串連到RabbitMQ,需要執行個體化一個ConnectionFactory並將其配置為使用所需的主機名稱,虛擬機器主機和憑據。 然後使用ConnectionFactory.CreateConnection()開啟一個串連。 以下兩個程式碼片段串連到hostName上的RabbitMQ節點:
ConnectionFactory factory = new ConnectionFactory(); // "guest"/"guest" by default, limited to localhost connections factory.UserName = user; factory.Password = pass; factory.VirtualHost = vhost; factory.HostName = hostName; IConnection conn = factory.CreateConnection(); ConnectionFactory factory = new ConnectionFactory(); factory.Uri = "amqp://user:[email protected]:port/vhost"; IConnection conn = factory.CreateConnection();
由於.NET用戶端使用比其他用戶端更嚴格的AMQP 0-9-1 URI規範解釋,因此在使用URI時必須小心。 特別是,主機部分不能被忽略,具有空名稱的虛擬機器主機不可定址。 所有出廠屬性都有預設值。 如果屬性在建立串連之前保持未分配,則將使用屬性的預設值:
Username "guest" Password "guest" Virtual host "/" Hostname "localhost" port 5672 是針對一般而言的串連, 5671 是針對 TLS 串連的
IConnection介面可以開啟一個通道:
IModel channel = conn.CreateModel();
通道Channel用於接收和發送訊息
3、使用訊息交換器和隊列
用戶端應用程式將與訊息交換器和訊息佇列(AMQP 0-9-1的進階構建塊)配合工作。 【訊息交換器】和【訊息佇列】在使用之前必須先聲明他們。 聲明任何類型的對象只是確保其中一個名稱存在,如有必要,建立它。 繼續前面的例子,以下代碼聲明一個訊息交換器和一個隊列,然後將它們綁定在一起。
model.ExchangeDeclare(exchangeName, ExchangeType.Direct); model.QueueDeclare(queueName, false, false, false, null); model.QueueBind(queueName, exchangeName, routingKey, null);
這將聲明了以下兩個對象:
【1】、非持久、非自動刪除的、交換類型為“direct”的訊息交換器;
【2】、非持久、非自動刪除、非排他的訊息佇列
可以通過使用附加參數來定製訊息交換器。 然後,上面的代碼使用給定的路由鍵將隊資料行繫結到訊息交換器。 請注意,許多通道API(IModel)方法重載。 ExchangeDeclare方便的簡單形式使用合理的預設值。 還有更多的表單具有更多的參數,可以根據需要修改這些預設值,並在需要時進行完全控制。 在整個API中使用這種“短版本,長版本”模式。
4、發布訊息
要將訊息發布到訊息交換器,請使用IModel.BasicPublish,如下所示:
byte[] messageBodyBytes = System.Text.Encoding.UTF8.GetBytes("Hello, world!"); model.BasicPublish(exchangeName, routingKey, null, messageBodyBytes);
為了精細控制,您可以使用重載變數來指定強制標誌,或指定訊息屬性:
byte[] messageBodyBytes = System.Text.Encoding.UTF8.GetBytes("Hello, world!"); IBasicProperties props = model.CreateBasicProperties(); props.ContentType = "text/plain"; props.DeliveryMode = 2; model.BasicPublish(exchangeName, routingKey, props, messageBodyBytes);
這將發送一個帶有發送模式為2(持久性)和內容類型是“text / plain”的訊息。 有關可用訊息屬性的更多資訊,請參閱IBasicProperties介面的定義。
在以下樣本中,我們使用自訂標題發布訊息:
byte[] messageBodyBytes = System.Text.Encoding.UTF8.GetBytes("Hello, world!"); IBasicProperties props = model.CreateBasicProperties(); props.ContentType = "text/plain"; props.DeliveryMode = 2; props.Headers = new Dictionary<string, object>(); props.Headers.Add("latitude", 51.5252949); props.Headers.Add("longitude", -0.0905493); model.BasicPublish(exchangeName, routingKey, props, messageBodyBytes);
下面的樣本設定訊息到期:
byte[] messageBodyBytes = System.Text.Encoding.UTF8.GetBytes("Hello, world!"); IBasicProperties props = model.CreateBasicProperties(); props.ContentType = "text/plain"; props.DeliveryMode = 2; props.Expiration = "36000000" mode.BasicPublish(exchangeName, routingKey, props, messageBodyBytes);
5、擷取個人訊息(“拉API”)
要檢索單個訊息,請使用IModel.BasicGet。 返回的值是BasicGetResult的執行個體,可以從中提取基本屬性和訊息體:
bool noAck = false;BasicGetResult result = channel.BasicGet(queueName, noAck);if (result == null) { // No message available at this time.} else { IBasicProperties props = result.BasicProperties; byte[] body = result.Body; ...
由於noAck = false,您還必須調用IModel.BasicAck來確認您已成功接收並處理該訊息:
... // acknowledge receipt of the message channel.BasicAck(result.DeliveryTag, false);}
請注意,使用此API擷取訊息效率相對較低。 如果您希望RabbitMQ將訊息推送給用戶端,請參閱下一節。
6、通過訂閱檢索郵件(“推送API”)
接收訊息的另一種方法是使用IBasicConsumer介面建立訂閱。 然後,訊息將在其到達時自動發送,而不必主動請求。 實現【消費者】的一種方法是使用便利類EventingBasicConsumer,它將傳送和其他【消費者】生命週期事件以C#事件:
var consumer = new EventingBasicConsumer(channel);consumer.Received += (ch, ea) => { var body = ea.Body; // ... process the message channel.BasicAck(ea.DeliveryTag, false); };String consumerTag = channel.BasicConsume(queueName, false, consumer);
另一個選項是根據子類DefaultBasicConsumer,覆蓋方法,或者直接實現IBasicConsumer。 你一般會想實現核心方法IBasicConsumer.HandleBasicDeliver。 更複雜的消費者將需要實施進一步的方法。 特別地,HandleModelShutdown使通道/串連關閉。 【消費者】還可以實現HandleBasicCancelOk以獲得取消通知。 DefaultBasicConsumer的ConsumerTag屬性可用於檢索伺服器產生的使用者標籤,如果沒有提供給原始的IModel.BasicConsume調用。 您可以使用IModel.BasicCancel取消活躍的消費者:
channel.BasicCancel(consumerTag);
在調用API方法時,您總是通過【消費者】標籤來引用【消費者】,【消費者】標籤可以是用戶端或伺服器產生的,如AMQP 0-9-1規範文檔中所述。
7、【消費者】的並發注意事項
在當前實現中,每個IConnection執行個體都由一個從通訊端讀取的後台線程支援,並將產生的事件指派到應用程式。 如果啟用了心跳,則從3.5.0版開始,它們將以.NET定時器方式實現。 因此,通常使用此庫的應用程式中至少有兩個線程處於活動狀態:
應用程式線程
包含應用程式邏輯,並調用IModel方法來執行協議操作。
I / O活動線程
隱藏並由IConnection執行個體完全管理。
在應用程式中可以看到執行緒模式的本質的一個地方是在庫中的應用程式註冊的任何回調。 這種回調包括:
任何IBasicConsumer方法
在IModel上的BasicReturn事件
IConnection,IModel等各種關機事件
8、【消費者】回調和訂閱
從版本3.5.0開始,應用程式回調處理常式可以調用阻塞操作(如IModel.QueueDeclare或IModel.BasicCancel)。 IBasicConsumer回調同時被調用。 但是,每通道操作命令被保留。 換句話說,如果訊息A和B按照同一個頻道的順序傳送,則按照此順序進行處理。 如果訊息A和B在不同的通道上傳送,則可以以任何順序(或並行)處理訊息。 由【.NET運行時】提供的、預設的TaskScheduler的任務分發器中調用【消費者】的回調。
9、使用自訂工作排程器
通過設定ConnectionFactory.TaskScheduler可以使用自訂任務發送器:
public class CustomTaskScheduler:TaskScheduler{ // ...}var cf = new ConnectionFactory();cf.TaskScheduler = new CustomTaskScheduler();
例如,這可以用於通過自訂TaskScheduler來限制並發程度。
10、在多線程中共用通道Chanel
作為經驗法則,IModel執行個體不應同時被多個線程使用:應用程式代碼應該保持對IModel執行個體的線程所有權的清晰認識。 如果多個線程需要訪問特定的IModel執行個體,應用程式應該強制執行互斥。 實現此目的的一種方法是為IModel的所有使用者鎖定執行個體本身:
IModel ch = RetrieveSomeSharedIModelInstance();lock (ch) { ch.BasicPublish(...);}
IModel操作錯誤一系列的癥狀包括但不限於,
線上上發送無效幀序列(例如,如果同時運行多個BasicPublish操作,則發生)和/或從類RpcContinuationQueue中的方法拋出NotSupportedException異常,提示“管道的請求是被禁止的【Pipelining of requests forbidden】”(在同時運行多個AMQP 0-9-1同步操作(如ExchangeDeclare)的情況下發生)。
11、處理不可路由的訊息
如果發布了一個設定了“強制”標誌的訊息,但未能送達,則代理將訊息返回給發送的用戶端(通過basic.return AMQP 0-9-1命令)。 要獲得此類通知,用戶端可以訂閱IModel.BasicReturn事件。 如果沒有附加事件的監聽器,則返回的訊息將被靜默地丟棄。
model.BasicReturn += new RabbitMQ.Client.Events.BasicReturnEventHandler(...);
如果用戶端把一條標識為“mandatory”的訊息發送到了類型為【Direct】的【訊息交換器Exchange】,但是這個exchange還沒有綁定到一個訊息佇列的時候,BasicReturn事件就會被觸發。
12、從RabbitMQ中斷連線
要中斷連線,只需關閉通道和串連:
channel.Close(200, "Goodbye");conn.Close();
請注意,關閉通道是很好的做法,但不是必要的 - 當底層串連關閉時,它將自動完成。 在某些情況下,您可能希望串連上的最後一個開啟的通道關閉的時候串連也關閉, 要實現此目的,請將IConnection.AutoClose屬性設定為true,但僅在建立第一個通道後:
IConnection conn = factory.CreateConnection(...);IModel channel = conn.CreateModel();conn.AutoClose = true;
當AutoClose為true時,最後關閉的通道也將導致串連關閉。 如果在建立任何通道之前設定為true,則串連將在那時關閉。
好了,暫時翻譯到此吧,其實還有一些沒翻譯完,暫時就不翻譯了,有時間再繼續。
再把原文的地址貼出來,想看完整的可以通過串連瀏覽。地址如下:http://www.rabbitmq.com/dotnet-api-guide.html
RabbitMQ系列教程之七:RabbitMQ的 C# 用戶端 API 的簡介