【Azure Service Bus】 Service Bus如何確保消息發送成功,發送端是否有Ack機制 

問題描述

Service Bus如何確保消息發送成功,發送端是否有Ack機制(是否有回調API告訴發送端,服務端已經收到消息)?根據對.NET發送Service Bus消息代碼的分析,發送方法queueClient.SendAsync(message)並無返回值,因此沒法知道發送消息是否成功。git

 

 

問題根源

Azure 服務總線已針對持久性進行優化,會確保在服務確認請求成功以前,發送到服務總線的全部數據將提交到存儲。一旦服務總線成功「ACK」(確認)請求,即表示服務總線已成功處理該請求。 若是服務總線返回「NACK」(失敗),則表示服務總線沒法處理該請求,客戶端應用程序必須重試該請求。官方提供的SDK,在沒有自定義RetryPolicy的狀況下,都會採用默認的重試機制。github

 

Service Bus .Net SDK 默認的重試機制(RetryPolicy)爲:c#

  • DeltaBackoff: 重試之間的間隔時間
  • MaxRetryCount: 最大重試次數
  • MaximumBackoff: 最大的間隔時間
  • MinimalBackoff: 最小的間隔時間

 

因此在調用Service Bus SDK發送消息時,若是代碼正常執行且沒有Exception,則表示消息成功發送。api

 

一句話總結爲:無錯即成功,失敗看異常。服務器

 

另外也有以下兩種發送倆查看消息:網絡

方式一:在Azure Service Bus門戶中查看指標 Incoming request/message

 

 

方式二:經過Servie Bus Explorer工具查看發送消息的內容

 

Service Bus異常消息類型

  1. 用戶代碼錯誤(System.ArgumentExceptionSystem.InvalidOperationExceptionSystem.OperationCanceledExceptionSystem.Runtime.Serialization.SerializationException)。 常規操做:繼續以前嘗試修復代碼。
  2. 設置/配置錯誤(Microsoft.ServiceBus.Messaging.MessagingEntityNotFoundExceptionSystem.UnauthorizedAccessException)。 常規操做:檢查配置,必要時進行更改。
  3. 暫時性異常(Microsoft.ServiceBus.Messaging.MessagingExceptionMicrosoft.ServiceBus.Messaging.ServerBusyExceptionMicrosoft.ServiceBus.Messaging.MessagingCommunicationException)。 常規操做:重試操做或通知用戶。 客戶端 SDK 中的 RetryPolicy 類能夠配置爲自動處理重試。 有關詳細信息,請參閱重試指南
  4. 其餘異常(System.Transactions.TransactionExceptionSystem.TimeoutExceptionMicrosoft.ServiceBus.Messaging.MessageLockLostExceptionMicrosoft.ServiceBus.Messaging.SessionLockLostException)。 常規操做:特定於異常類型。

 

異常類型

下表列出了消息異常的類型及其緣由,並說明能夠採起的建議性操做。session


異常類型
異常類型 說明/緣由/示例 建議的操做 自動/當即重試注意事項
TimeoutException 服務器在 OperationTimeout 控制的指定時間內未響應請求的操做。 服務器可能已完成請求的操做。 這多是因爲網絡或其餘基礎結構延遲形成的。 檢查系統狀態的一致性,並根據須要重試。 請參閱超時異常 在某些狀況下,重試可能會有幫助;在代碼中添加劇試邏輯。
InvalidOperationException 不容許在服務器或服務中執行請求的用戶操做。 有關詳細信息,請查看異常消息。 例如,若是在 ReceiveAndDelete 模式下收到消息,則 Complete() 將生成此異常。 檢查代碼和文檔。 確保請求的操做有效。 重試不起做用。
OperationCanceledException 嘗試對已關閉、停止或釋放的對象調用某個操做。 在極少數狀況下,環境事務已釋放。 檢查代碼並確保代碼不會對已釋放的對象調用操做。 重試不起做用。
UnauthorizedAccessException TokenProvider 對象沒法獲取令牌,該令牌無效,或者令牌不包含執行操做所需的聲明。 確保使用正確的值建立令牌提供程序。 檢查訪問控制服務的配置。 在某些狀況下,重試可能會有幫助;在代碼中添加劇試邏輯。
ArgumentException
ArgumentNullException
ArgumentOutOfRangeException
提供給該方法的一個或多個參數均無效。
提供給 NamespaceManager 或 Create 的 URI 包含路徑段。
提供給 NamespaceManager 或 Create 的 URI 方案無效。
屬性值大於 32 KB。
檢查調用代碼並確保參數正確。 重試不起做用。
MessagingEntityNotFoundException 與操做關聯的實體不存在或已被刪除。 確保該實體存在。 重試不起做用。
MessageNotFoundException 嘗試接收具備特定序列號的消息。 找不到此消息。 確保該消息還沒有接收。 檢查死信隊列,以肯定該消息是否被視爲死信。 重試不起做用。
MessagingCommunicationException 客戶端沒法與服務總線創建鏈接。 確保提供的主機名正確而且主機可訪問。

若是你的代碼在使用防火牆/代理的環境中運行,請確保到服務總線域/IP 地址和端口的流量未被阻止。app

若是存在間歇性的鏈接問題,重試可能會有幫助。
ServerBusyException 服務目前沒法處理請求。 客戶端能夠等待一段時間,並重試操做。 客戶端可在特定的時間間隔後重試操做。 若是重試致使其餘異常,請檢查該異常的重試行爲。
MessagingException 在如下狀況下,可能會引起通常消息異常:

嘗試使用屬於其餘實體類型(例如主題)的名稱或路徑建立 QueueClientasync

嘗試發送大於 256 KB 的消息。ide

服務器或服務在處理請求期間遇到錯誤。 有關詳細信息,請查看異常消息。 這一般是暫時性異常。

 

因爲實體正受到限制,所以已終止請求。 錯誤代碼:5000一、5000二、50008。

檢查代碼,並確保只對消息正文使用可序列化對象(或使用自定義序列化程序)。

在文檔中查看屬性支持的值類型,並只使用支持的類型。

檢查 IsTransient 屬性。 若是爲 true,能夠重試操做。

若是異常是因爲限制致使的,請等待幾秒鐘,而後重試該操做。 重試行爲未定義,在其餘場景中可能沒有幫助。
MessagingEntityAlreadyExistsException 嘗試使用已被該服務命名空間中另外一實體使用的名稱建立實體。 刪除現有的實體,或者選擇不一樣的名稱來建立實體。 重試不起做用。
QuotaExceededException 消息實體已達到其容許的最大大小,或已超出到命名空間的最大鏈接數。 經過從實體或其子隊列接收消息在該實體中建立空間。 請參閱QuotaExceededException 若是同時已刪除消息,則重試可能會有幫助。
RuleActionException 若是嘗試建立無效的規則操做,服務總線將返回此異常。 若是在處理該消息的規則操做時出錯,服務總線會將此異常附加到死信消息。 檢查規則操做是否正確。 重試不起做用。
FilterException 若是嘗試建立無效的篩選器,服務總線將返回此異常。 若是在處理該消息的篩選器時出錯,服務總線會將此異常附加到死信消息。 檢查篩選器是否正確。 重試不起做用。
SessionCannotBeLockedException 嘗試接受具備特定會話 ID 的會話,但該會話當前已被另外一客戶端鎖定。 確保該會話未由其餘客戶端鎖定。 若是在此期間會話已釋放,則重試可能會有幫助。
TransactionSizeExceededException 事務包含過多的操做。 減小此事務中操做的數目。 重試不起做用。
MessagingEntityDisabledException 對已禁用的實體請求運行時操做。 激活實體。 若是在此期間該實體已激活,則重試可能會有幫助。
NoMatchingSubscriptionException 若是向已啓用預篩選的主題發送消息而且全部篩選器都不匹配,則服務總線返回此異常。 確保至少有一個篩選器匹配。 重試不起做用。
MessageSizeExceededException 消息有效負載超出 256 KB 限制。 256-KB 限制是指總消息大小,可能包括系統屬性和任何 .NET 開銷。 減小消息負載的大小,並重試操做。 重試不起做用。
TransactionException 環境事務 (Transaction.Current) 無效。 該事務可能已完成或已停止。 內部異常可能提供了更多信息。   重試不起做用。
TransactionInDoubtException 已對未決事務嘗試進行操做,或嘗試提交該事務而且事務進入不肯定狀態。 應用程序必須處理此異常(做爲特例),由於此事務可能已提交。

參考資料

Service Bus Explorer: https://github.com/paolosalvatori/ServiceBusExplorer/releases

Service Bus Retry Policy: https://docs.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#service-bus

相關文章
相關標籤/搜索