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

路邊兩盞燈發表於2020-12-21

問題描述

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

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

 

 

問題根源

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

 

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

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

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

 

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

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

 

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

 

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

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

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

 

 

方式二:通過Servie Bus Explorer工具檢視傳送訊息的內容

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

 

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
提供給該方法的一個或多個引數均無效。
提供給 NamespaceManager 或 Create 的 URI 包含路徑段。
提供給 NamespaceManager 或 Create 的 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

 

相關文章