私はこれを行うための単一の普及したパターンを見つけることができませんでした。しかし、System.Messagingをちょっと調べてみると、メッセージのプロパティとMSMQの動作を活用して、最小限の可動部分で作業を完了させる適切な方法だと思いました。
これは私が実装したものです。それはかなり単純で軽量であることが判明 - あまりないコードや保守が容易:
私は3つのプロパティを持つRetryLevelと呼ばれるオブジェクトを作成しました:
int型の注文、 int型NumberOfRetries、 のTimeSpanディレイ
を
受信側アプリケーションの構成にRetryLevelのリストが追加されました。したがって、新しい機能は基本的にnレベルの再試行をサポートします。
次に、RetryInfoというオブジェクトを作成しました。
INT試行、 列SourceQueuePath
RetryInfoオブジェクトのインスタンスがシリアル化と再試行されてしまう各メッセージの拡張プロパティに格納されます。このオブジェクトは、2つのプロパティを有します。これにより、メッセージ自体の現在の再試行状態を追跡することができるため、別の再試行メタデータストアを維持する必要がなくなり、メッセージIDを調整してデータを同期させるなどのオーバーヘッドが発生しません。
最後に、受信者の構成への待ち行列経路。このキューでは、メッセージが「タイムアウト」中にドロップされます。
メッセージハンドラがメッセージを拒否すると、受信者はRetryInfoがあればそれをデシリアライズし、(前回の)試行回数を調べて、到達したRetryLevelsのどれかを判断します。
受信者は、メッセージのTimeToBeRecieved(TTBR)プロパティをDateTime.Nowに設定し、適切なRetryLevelの遅延値を設定します。次に、RetryInfoのSourceQueuePathプロパティから作成されたQueueにAdministrativeQueueプロパティを設定し、メッセージのAcknowledgeTypeをAcknowledgeTypes.NegativeReceiveに設定します。最後に、メッセージを待ち行列に入れます。
ここから、MSMQはメッセージのTTBRを監視します。タイムアウトすると、MSMQはそのメッセージを元のキューから取得したAdministrativeQueueプロパティのキューに戻します。メッセージがハンドラによって引き続き拒否される場合、RetryLevelsの上に移動します。
メッセージの試行回数が、設定されたRetryLevelsのNumberOfRetriesのそれを超えている場合、メッセージのTTBRプロパティはTimeSpan.Zeroに設定され、UseDeadLetterQueueプロパティはtrueに設定され、メッセージはいずれかと同様に待機キューに入れられます他の再試行。ただし、今回はすぐにタイムアウトし、MSMQは待ち行列のホストのシステムデッドレターキュー(DLQ)にそれを送ります。このキューでは、手動で処理することができます。
ありがとうございます。私は、WCFのように、再試行機能を持つMSMQの上に構築されたアプリケーションであるNServiceBusとMassTransitを認識しています。しかし、私の質問は、MSMQの上にアプリケーションを構築する場合、リトライ機能を作成するための良い方法です。私のアプリケーションを別のものに置き換える良い方法ではありません。 –