2012-01-10 11 views
3

シナリオ:NServiceBus - 異なるスレッド/プロセスでBus.Send()が発生したときのメッセージハンドラの順序を制御する方法は?

NServiceBus経由で監査メッセージを送信するシナリオがあります。ハンドラは既存のデータベーステーブルに行を挿入して更新しますが、変更は不要です。監査データに正しいシステム状態が反映されるように、メッセージの処理順序を制御する必要があります。順不同で処理されたメッセージは、監査データに誤った状態が反映される可能性があります。

監査データの中には特定の順序が想定されているものもありますが、プロセス中に何度も送信される状態更新など、最初のメッセージの後にいつでも受信できるものもあります。私は次のように構成されたエンドポイントを持つサーバー、(特にISpecifyMessageHandlerOrdering機能)を使用してテストしてきた私のテストプロジェクトで

public class MyServer : IConfigureThisEndpoint, AsA_Server, ISpecifyMessageHandlerOrdering 
    { 
      public void SpecifyOrder(Order order) 
      { 
       order.Specify(First<PrimaryCommand>.Then<SecondaryCommand>()); 
      } 
    } 

メッセージの明示的な順序が知られていないので、一つのメッセージ、 InitialAuditMessageは最初のメッセージで、PrimaryCommandから継承します。

後で受信できる他のメッセージは、SecondaryCommandから継承します。

public class StartAuditMessage : PrimaryCommand 
public class UpdateAudit1Message : SecondaryCommand 
public class UpdateAudit2Message : SecondaryCommand 
public class ProcessUpdateMessage : SecondaryCommand 

これは、同じスレッドから送信されたメッセージの処理順序を制御する際に機能します。

ただし、メッセージが別のスレッドまたはプロセスから送信された場合、これは機能しません。これは、関連するメッセージをリンクするものがないため意味があります。

メッセージを別のスレッドから送信したときに順不同で処理されないように、何らかのIDのようにメッセージをリンクするにはどうすればよいですか?これはSagasのユースケースですか?

また、ステータス更新メッセージに関しては、同じタイプのメッセージが送信された順に処理されるようにするにはどうすればよいですか?

+1

監査行に何らかの種類のタイムスタンプがありますか?そのスタンプに基づいて行を選択したり並べ替えたりすることができます。 –

+0

不幸なことに、この表を変更することはありません。 – gb2d

答えて

1

注文処理の要件がある場合は、処理のある時点ですべてを1つのスレッドに限定する必要があるという結論を避けることはできません。単一スレッドは、処理される順序を保証します。

場合によっては、処理を相関識別子で分割して、1つのスレッドを複数のスレッドに「スケールアウト」することができます。相関IDを使用すると、順序を維持する必要があるメッセージの論理グループを定義できます。これにより、より効率的な順序付けられた処理をそれぞれ実行する同時スレッドを持つことができます。

+0

私は、単一のスレッドが順序を保持していないと主張します。メッセージが失敗し、エラーキューで終了し、再試行のために元のキューに戻される場合のシナリオについて考えてみましょう。 –

+0

メッセージを再シーケンスする場合(http://www.eaipatterns.com/Resequencer.html)、すべてのメッセージが正常に処理されるまで順序付けられたバッチをブロックし、それにより順序を維持することによって、障害を回避する。私の要点は、注文された納品では、注文を維持するためにどこかで単一のスレッドが絶対に必要であるということでした。 –

+0

この返答のように見えます。これを処理する別の手段が考案されています! – gb2d

関連する問題