Dot-Net

如何處理 WCF 的 MSMQ 綁定中的消息失敗

  • May 28, 2012

我創建了一個 WCF 服務並正在使用 netMsmqBinding 綁定。

這是一個簡單的服務,它將 Dto 傳遞給我的服務方法並且不期望響應。消息被放置在一個 MSMQ 中,並且一旦被拾取就插入到一個數據庫中。

確保沒有數據失去的最佳方法是什麼。

我嘗試了以下兩種方法:

  1. 拋出異常

這會將消息置於死信隊列中以供手動閱讀。當我的服務開始時,我可以處理這個 2. 在綁定上設置 receiveRetryCount=“3”

經過 3 次嘗試後 - 瞬間發生,這似乎將消息留在隊列中,但我的服務出錯了。重新啟動我的服務會重複此過程。

理想情況下,我想做以下事情:

嘗試處理消息

  • 如果失敗,請等待該消息 5 分鐘,然後重試。
  • 如果該過程失敗 3 次,則將消息移動到死信隊列。
  • 重新啟動服務會將死信隊列中的所有消息推回隊列中,以便對其進行處理。

我能做到這一點嗎?如果有怎麼辦?你能給我指出任何關於如何最好地利用 WCF 和 MSMQ 來處理我給定場景的好文章嗎?

任何幫助將非常感激。謝謝!

一些附加資訊

我在 Windows XP 和 Windows Server 2003 上使用 MSMQ 3.0。不幸的是,我無法使用針對 MSMQ 4.0 和 Vista/2008 的內置有害消息支持。

SDK 中有一個範例可能對您的情況有用。基本上,它所做的是將 IErrorHandler 實現附加到您的服務,當 WCF 將消息聲明為“毒藥”(即,當所有配置的重試都已用盡時)時,它將擷取錯誤。該範例所做的是將消息移動到另一個隊列,然後重新啟動與該消息關聯的 ServiceHost(因為在發現有害消息時它會出現故障)。

這不是一個非常漂亮的範例,但它可能很有用。但是有幾個限制:

1-如果您有多個與您的服務相關聯的端點(即通過多個隊列公開),則無法知道有毒消息到達哪個隊列。如果您只有一個隊列,這不會成為問題。我還沒有看到任何官方的解決方法,但我已經嘗試了一種可能的替代方案,我在這裡記錄了:http ://winterdom.com/weblog/2008/05/27/NetMSMQAndPoisonMessages.aspx

2-一旦問題消息被移動到另一個隊列,它就成為您的責任,因此一旦超時完成(或將新服務附加到該隊列以處理它),由您決定將其移回處理隊列。

老實說,在任何一種情況下,您都會在這裡看到一些 WCF 本身並沒有涵蓋的“手動”工作。

我最近一直在從事一個不同的項目,我需要明確控制重試發生的頻率,我目前的解決方案是創建一組重試隊列並在重試隊列和主處理隊列之間手動移動消息基於一組計時器和一些啟發式方法,僅使用原始 System.Messaging 東西來處理 MSMQ 隊列。它似乎工作得很好,但如果你這樣做會有幾個問題。

我認為使用 MSMQ(僅在 Vista 上可用)您可以這樣做:

<bindings>
   <netMsmqBinding>
       <binding name="PosionMessageHandling"
            receiveRetryCount="3"
            retryCycleDelay="00:05:00"
            maxRetryCycles="3"
            receiveErrorHandling="Move" />
   </netMsmqBinding>
</bindings>

WCF 將在第一次呼叫失敗後立即重試 ReceiveRetryCount 次。批處理失敗後,消息將移至重試隊列。延遲 RetryCycleDelay 分鐘後,消息從重試隊列移動到端點隊列,並重試批處理。這將重複 MaxRetryCycle 時間。如果所有失敗,則根據receiveErrorHandling 處理消息,該消息可以移動(到毒隊列)、拒絕、丟棄或故障

順便說一句,關於 WCF 和 MSMQ 的好文章是來自 Juval Lowy 的 Progammig WCF 書的第 9 章

引用自:https://stackoverflow.com/questions/82099