天天看點

【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: 最小的間隔時間
【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.ArgumentException、System.InvalidOperationException、System.OperationCanceledException、System.Runtime.Serialization.SerializationException)。 正常操作:繼續之前嘗試修複代碼。
  2. 設定/配置錯誤(Microsoft.ServiceBus.Messaging.MessagingEntityNotFoundException、System.UnauthorizedAccessException)。 正常操作:檢查配置,必要時進行更改。
  3. 暫時性異常(Microsoft.ServiceBus.Messaging.MessagingException、Microsoft.ServiceBus.Messaging.ServerBusyException、Microsoft.ServiceBus.Messaging.MessagingCommunicationException)。 正常操作:重試操作或通知使用者。 用戶端 SDK 中的 

    RetryPolicy

     類可以配置為自動處理重試。 有關詳細資訊,請參閱重試指南。
  4. 其他異常(System.Transactions.TransactionException、System.TimeoutException、Microsoft.ServiceBus.Messaging.MessageLockLostException、Microsoft.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

當在複雜的環境中面臨問題,格物之道需:濁而靜之徐清,安以動之徐生。 雲中,恰是如此!