2

私のチームには、http バインディングを使用して wcf サービスをホストする Windows サービスがあります。wcf サービスがメッセージを受信すると、これも Windows サービスでホストされている NetMsmqBinding を使用して、すぐに別の wcf サービスにメッセージを送信します。msmq サービスはメッセージを処理し、DB に保存します。

開発環境とステージング環境では、すべてが正常に機能しました。ただし、本番環境にデプロイしたとき、サービスに送信されたメッセージが n+1 の係数で乗算されていることがわかりました (n メッセージの場合)。

例: 1 件のメッセージが受信され、2 件が DB に保存されました。4通の受信、20通のDB保存など

トランザクションの msmq サービス設定と関係があると思われます。

同時実行性、および InstanceContextMode ですが、それを理解することはできません。

サービスの設定は次のとおりです。

  • InstanceContextMode: デフォルト。
  • ConcurrencyMode: デフォルト
  • トランザクション: TransactionScoreRequired = True および TransactionAutoComplete = True。
  • RetryCount = 1、RetryCycles = 1

.Net 4、MSMQ 3.0、および Windows Server 2003 を使用しています。

この問題の原因についてのアイデアはありますか?

編集:

多くの調査の結果、次のことがわかりました。

  • wcf ランタイムが 1 つのメッセージのトランザクションをコミットしようとすると、「トランザクションが非同期的に中止されました」という例外がスローされます。この例外は、メッセージが複製されるたびにスローされます。
  • wcf トレースでは、上記以外の例外は見られません。
  • System.Transaction トレースでは、(最初のメッセージに対して) トランザクションが開かれていることがわかります。次に、wcf ランタイムがそのトランザクションのクローンを (プロパティ RollbackIfNotCompleted=true で) 作成した後、数秒経過してもメッセージはありません。トレースすると、同じことが再び起こります。

私たちは本当に無知です...

ありがとう

4

2 に答える 2

3

アプリケーションがメッセージを削除するか、TimeToBeReceived タイマーの期限が切れない限り、MSMQ はメッセージを削除しません。

あなたの環境を正しく理解していれば、受信メッセージの処理時間が長すぎることが原因である可能性があります。メッセージの受信と再送信が同じトランザクション内で行われる場合、最終的にキューから削除される前に、最初の WCF サービスが同じメッセージを複数回読み取ろうとする可能性があります。

これにより、次のアイデアを試すことができます。

  • 元のメッセージを受信した後、まったく同じ内容の新しいメッセージを作成し、新しいメッセージを次の WCF サービスに送信しようとする場合があります。これにより、受信したメッセージの寿命が短くなります。

  • メッセージの同じ順序を保持する必要がある場合は、Miker169 の提案を試して、構成を次のように変更できますInstanceContextMode.Single , ConcurrencyMode = ConcurrencyMode.Single( https://stackoverflow.com/a/2610093/219344 )

于 2013-03-04T14:51:08.710 に答える
2

さて、ついにそれを手に入れました。ログには Entlib を使用し、DB リスナーを追加しました。Entlib DB リスナーは、サービスの同じトランザクションを使用します。トランザクションを DB サーバーに渡そうとすると、DB サーバーで MSDTC が正しく構成されていないためにエラーがスローされ、トランザクションがロールバックされます。WCF ランタイムがトランザクションをコミットしようとすると、既に中止されているため失敗し、同じメッセージを再度処理しようとします (組み込みの再試行メカニズムのため)。

MSDTC 設定を修正したところ、重複が停止しました。
ここで、理解する必要があるのは、なぜサービス トランザクションへのロールバックによってメッセージが何度も増加するのかということだけです。

于 2013-03-04T18:05:10.990 に答える