1. 程式人生 > 實用技巧 >【Azure Service Bus】 Service Bus如何確保訊息傳送成功,傳送端是否有Ack機制 

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

問題描述

Service Bus如何確保訊息傳送成功,傳送端是否有Ack機制(是否有回撥API告訴傳送端,服務端已經收到訊息)?根據對.NET傳送Service Bus訊息程式碼的分析,傳送方法queueClient.SendAsync(message)並沒有返回值,所以無法知道傳送訊息是否成功。

問題根源

Azure服務匯流排已針對永續性進行優化,會確保在服務確認請求成功之前,傳送到服務匯流排的所有資料將提交到儲存。一旦服務匯流排成功“ACK”(確認)請求,即表示服務匯流排已成功處理該請求。如果服務匯流排返回“NACK”(失敗),則表示服務匯流排無法處理該請求,客戶端應用程式必須重試該請求。官方提供的SDK,在沒有自定義RetryPolicy的情況下,都會採用預設的重試機制。

Service Bus.Net SDK 預設的重試機制(RetryPolicy)為:

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

所以在呼叫Service Bus SDK傳送訊息時,如果程式碼正常執行且沒有Exception,則表示訊息成功傳送。

一句話總結為:無錯即成功,失敗看異常。

另外也有如下兩種傳送倆檢視訊息:

方式一:在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)。常規操作:特定於異常型別。

異常型別

下表列出了訊息異常的型別及其原因,並說明可以採取的建議性操作。


異常型別
異常型別說明/原因/示例建議的操作自動/立即重試注意事項
TimeoutException 伺服器在OperationTimeout控制的指定時間內未響應請求的操作。伺服器可能已完成請求的操作。這可能是由於網路或其他基礎結構延遲造成的。 檢查系統狀態的一致性,並根據需要重試。請參閱超時異常 在某些情況下,重試可能會有幫助;在程式碼中新增重試邏輯。
InvalidOperationException 不允許在伺服器或服務中執行請求的使用者操作。有關詳細資訊,請檢視異常訊息。例如,如果在ReceiveAndDelete模式下收到訊息,則Complete()將生成此異常。 檢查程式碼和文件。確保請求的操作有效。 重試不起作用。
OperationCanceledException 嘗試對已關閉、中止或釋放的物件呼叫某個操作。在極少數情況下,環境事務已釋放。 檢查程式碼並確保程式碼不會對已釋放的物件呼叫操作。 重試不起作用。
UnauthorizedAccessException TokenProvider物件無法獲取令牌,該令牌無效,或者令牌不包含執行操作所需的宣告。 確保使用正確的值建立令牌提供程式。檢查訪問控制服務的配置。 在某些情況下,重試可能會有幫助;在程式碼中新增重試邏輯。
ArgumentException
ArgumentNullException
ArgumentOutOfRangeException
提供給該方法的一個或多個引數均無效。
提供給NamespaceManagerCreate的 URI 包含路徑段。
提供給NamespaceManagerCreate的 URI 方案無效。
屬性值大於 32 KB。
檢查呼叫程式碼並確保引數正確。 重試不起作用。
MessagingEntityNotFoundException 與操作關聯的實體不存在或已被刪除。 確保該實體存在。 重試不起作用。
MessageNotFoundException 嘗試接收具有特定序列號的訊息。找不到此訊息。 確保該訊息尚未接收。檢查死信佇列,以確定該訊息是否被視為死信。 重試不起作用。
MessagingCommunicationException 客戶端無法與服務匯流排建立連線。 確保提供的主機名正確並且主機可訪問。

如果你的程式碼在使用防火牆/代理的環境中執行,請確保到服務匯流排域/IP 地址和埠的流量未被阻止。

如果存在間歇性的連線問題,重試可能會有幫助。
ServerBusyException 服務目前無法處理請求。 客戶端可以等待一段時間,並重試操作。 客戶端可在特定的時間間隔後重試操作。如果重試導致其他異常,請檢查該異常的重試行為。
MessagingException 在以下情況下,可能會引發一般訊息異常:

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

嘗試傳送大於 256 KB 的訊息。

伺服器或服務在處理請求期間遇到錯誤。有關詳細資訊,請檢視異常訊息。這通常是暫時性異常。

由於實體正受到限制,因此已終止請求。錯誤程式碼:50001、50002、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