この質問に答えるには3つの方法があると思います
- 直接の答え
- クライアントとサーバーを制御する状況のための代替アプローチ
- クライアントを制御しない別のアプローチ
最初に2と3の答えを出したいのですが(私はそれらの方が良いと思うので)、最後に直接答えます...約束します!
あなたの問題は、サービスが受信した順序でメッセージを処理する必要があるということではないと思います。独立したクライアントがあるため、メッセージがサービスから送信されたのと同じ順序で受信されることを保証できないということです。クライアント。
クライアントのアルファとベータの例を考えてみましょう。クライアントALPHAがオペレーションCを呼び出す前に、クライアントALPHAがオペレーション2を呼び出す要求を送信する場合でも、サービスが受け取る順序を知る方法はありません。これは、受信した順序でサーバーで処理したとしても、これは「間違った」順序である可能性があることを意味します。
これに同意する場合は、読み続けてください。そうでない場合は、この投稿の下部にある直接の回答に直接進んでください; o)
アプローチ1:WSトランザクションを使用する
サービスとクライアントの両方を制御し、クライアントがWS- * SOAPプロトコルを実装できる場合(.Net WCFクライアントなど)。次に、WS-Transactionプロトコルを使用して、単一の長時間実行トランザクションで処理されることを目的とした単一のクライアントからの操作が確実にそのように実行されるようにすることができます。
WCFを使用してWS-Transcationを実行する方法の詳細については、以下を参照してください。
http://msdn.microsoft.com/en-us/library/ms752261.aspx
クライアントALPHAとBETAの例に従うと、これによりクライアントALPHAは次のことが可能になります。
- トランザクションを開始します
- 操作1を呼び出す
- 操作2を呼び出す
- トランザクションをコミットする
クライアントでトランザクションを開始するALPHAの効果は、そのトランザクションをサーバーにフロースルーすることです。これにより、操作1と操作2が一緒に完了するか、まったく完了しないことを保証するDBトランザクションを作成できます。
これが行われている間にクライアントBETAが操作3を呼び出すと、トランザクションがコミットまたは中止されるまで待機するように強制されます。これにより、操作3がタイムアウトになる可能性があることに注意してください。その場合、BETAはそのエラーを処理する必要があります。
この動作は、またはのいずれInstanceContextMode
かで機能しますConcurrencyMode
。
ただし、欠点は、この種の長時間実行される分散トランザクションは、一般的にスケーラビリティに適していないことです。現在、数十人のクライアントがいますが、将来的には成長しますか?そして、クライアントは常にWS-Transactionを実装できますか?もしそうなら、これは良いアプローチかもしれません。
アプローチ2:「楽観的な」タイプのアプローチを使用する
多くの異なるクライアントタイプ(電話、ブラウザなど)をサポートする必要がある場合は、操作を任意の順序で実行できるようにし、サービスとクライアントロジックが障害を処理できるようにすることができます。
これは悪いように聞こえるかもしれませんが、
- サーバー側でデータベーストランザクション(上記のWS-Transactionトランザクションではない)を使用して、データベースが常に一貫していることを確認できます
- 各クライアントは独自の呼び出しを同期できるため、この例では、ALPHAは呼び出し1がOKを完了するのを待ってから、呼び出し2を実行します。
ここでの欠点は、必要な障害ロジックについて慎重に検討し、クライアントとサービスのコードが堅牢で適切に動作することを確認する必要があることです。
あなたの例では、ALPHAはそれ自体の呼び出しを同期できると述べましたが、ALPHAが操作1を呼び出した後、操作2を呼び出す前に、BETAが操作3を呼び出す場合、それは次のようになります。
- 操作2は失敗します(たとえば、操作3が操作2が更新しようとしているレコードを削除した場合)。その場合、その失敗を処理する必要があります。
- 操作3は操作3を上書きします(たとえば、操作3はレコードを更新し、操作2は同じレコードを更新しようとします)。この場合、あなたは何をすべきかを決める必要があります。操作2を成功させることができます。その場合、ベータ版からの更新は失われます。または、操作2で、レコードがALPHAによって読み取られてから変更されたことを検出して失敗するようにするか、ユーザーに通知して、変更を上書きするかどうかを決定させることができます。
MS Entity Frameworkのコンテキストでのこれに関する議論については、を参照してください。
http://msdn.microsoft.com/en-us/library/bb738618.aspx
それの一般的な議論については、を参照してください。
http://en.wikipedia.org/wiki/Optimistic_concurrency_control
ConcurrencyMode
繰り返しになりますが、WCFの用語では、これはどのInstanceContextMode
この種のアプローチは、スケーラビリティが重要な場合に使用される最も一般的なアプローチです。これの欠点は、ユーザーエクスペリエンスが低下する可能性があることです(たとえば、ユーザーが気付かないうちに変更が上書きされる可能性があります)。
元の質問への直接回答
メッセージが連続して処理されることを確実に確認する必要がある場合は、あなたが探していると思いますInstanceContextMode.Single
http://msdn.microsoft.com/en-us/library/system.servicemodel.instancecontextmode.aspx
これは、サービスクラスの単一のインスタンスがサービスアプリケーションの存続期間中に作成されることを意味します。ConcurrencyMode = Single
またはを使用する場合ConcurrencyMode = Reentrant
は、サービスが一度に1つのメッセージのみを処理し(インスタンスが1つあり、シングルスレッドであるため)、メッセージは受信された順序で処理されることを意味します。
を使用するConcurrencyMode = multiple
場合、単一のサービスインスタンスは、異なるスレッドで同時に複数のメッセージを処理するため、処理の順序は保証されません。
これがパフォーマンスにどの程度の悪影響を与えるかは、各サービス呼び出しの実行にかかる時間によって異なります。1秒あたり10を取得し、それぞれが0.1秒かかる場合は、問題ありません。1秒あたり20を取得し、それぞれが通常0.1秒かかる場合、平均時間は100%増加します。