Windows Server 2012 で実行されている社内サービス バスに送信されたメッセージのトランザクション処理に MSMQ を使用しており、メッセージ処理が失敗したときに問題が発生しました。
サービスのセットアップ
サービス
<endpoint address="net.msmq://localhost/private/quoteandbuy_transactions" binding="netMsmqBinding" bindingConfiguration="MsmqQuoteAndBuy" name="Msmq" contract="Soa.Net.EndPoints.IMessagingXmlProcessor" />
バインディング
<binding name="MsmqQuoteAndBuy" durable="true" exactlyOnce="true" maxRetryCycles="100" receiveErrorHandling="Move" receiveRetryCount="0" retryCycleDelay="01:00:00" useMsmqTracing="true" maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" />
<security mode="None">
<transport msmqAuthenticationMode="None" msmqProtectionLevel="None" />
<message clientCredentialType="None" />
</security>
</binding>
ご覧のとおり、メッセージごとに 100 回の再試行を制限して、1 時間ごとに実行されるサイクルがあります。メッセージの TTL は 24 時間 (デフォルト) であるため、これはデフォルトでは達成されません。
MSMQ にトランザクションがあり、サードパーティによってプロセスが実行されているために失敗する可能性があります。メッセージは再試行サブキューにドロップされます。さらにいくつか入ってきて、同じことが起こります。たとえば、20 回の失敗があるとします。
現状では、最初のメッセージ (場合によっては 2 番目のメッセージも?) のみが再試行され、これはおそらく同じ失敗したプロセスになるため、トランザクションを再びコミットしません。
再試行サイクルの期間に達したすべてのメッセージがメイン キューに移動されて再試行されることを期待しますが、これは起こりません。一番上のメッセージは、TTL に達するか、最終的に成功するまでブロックし続けます。
再試行期間に達したすべてのメッセージをブロックおよび処理しないようにキューの動作を設定する方法です。
たとえば、10 分以内に 20 件のメッセージが受信された場合、それらがすべて失敗した場合、最初のメッセージのみが 1 時間ごとに再試行され、残りの 19 件は最初のメッセージが TTL に達するまでそこに留まり、試行されます。 TTL に達したため、再試行キューからも削除されます。
メッセージングが FIFO ベースで機能することと、Vista で MSMQ を実行する前は、メッセージが失敗すると他のメッセージがブロックされるため、再試行メッセージ キューが発生することを理解しています。しかし、これは問題を再試行サブキューに移しただけではありませんか?