0

WCF サービスへの要求と応答をログに記録しようとしています。私が今までやったことは次のとおりです。

public class OutputMessageInspector : IDispatchMessageInspector
{
    int lastLogId;

   public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
   {
       // Parse request & read required information
       // Insert request data into log tables
       // Set lastLogId to the id created above
   }

   public void BeforeSendReply(ref Message reply, object correlationState)
   {
       // Parse reply
       // Using lastLogId update the response column in database table
   }
}

すべて正常に動作していますが、懸念事項が 1 つあります。

AfterReceiveRequest正しいレコードが更新BeforeSendReplyされるように、同期で作業する必要があります。BeforeSendReply私が念頭に置いているケースは、サービスが複数のクライアントから同時に呼び出されることです。質問:

  • lastLogId複数のリクエストとレスポンスの間で混乱したりシャッフルしたりしませんか?
  • このロギングBeforeSendReplyは、複数のクライアントが同時にサービスを呼び出している場合に特別に更新されますか? はいの場合は、私の心を安心させるために説明をお願いします。いいえの場合は、これに対するより良い解決策を提供してください。
4

2 に答える 2

4

要件に合わせて WCF ログを使用する @Schneiders ソリューションに同意します。

ただし、質問に答えるには:

このロギングは、BeforeSendReply で特別に更新され、複数のクライアントが同時にサービスを呼び出しても正常に機能しますか?

いいえ、それはしません。のインスタンスはIDispatchMessageInspectorコール間で共有されます。

メンバー プロパティを使用する代わりに、呼び出し固有のデータがcorrelationStateonを通じてサポートされIDispatchMessageInspectorます。AfterReceiveRequest()オブジェクトが返すものは何でもcorrelationStatetoとして渡されBeforeSendReply()ます。

つまり、次のようなものが機能するはずです。

public class OutputMessageInspector : IDispatchMessageInspector
{
   public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
   {
       // Parse request & read required information
       // Insert request data into log tables
       // Set lastLogId to the id created above
       return lastLogId
   }

   public void BeforeSendReply(ref Message reply, object correlationState)
   {
       // Parse reply
       int lastLogId = (int)correlationState;
   }
}
于 2014-09-12T15:01:06.920 に答える
1

まず、WCF には要求と応答をログに記録する機能が組み込まれているため、独自のソリューションを展開する前に調査する価値があるかもしれません。

あなたの問題に関しては、通常、IDispatchMessageInspector をサービスまたはエンドポイントの動作として適用し、ApplyDispatchBehavior をフックしています。そこで、おそらく新しい OutputMessageInspector を作成し、それを DispatchRuntime.MessageInspectors コレクションに追加しています。

動作は、サービスまたはエンドポイントが作成されたときに 1 回だけ適用されるため、DispatchRuntime が 1 つしかなく、MessageInspector を 1 つだけ作成していると推測でき、すべてのリクエスト/スレッドで共有されます。

その場合、OutputMessageInspector は「スレッドセーフ」である必要があります。そこに状態を保持する場合は、スクランブルされないようにアクセスを同期する必要があります。

于 2014-09-12T11:18:12.280 に答える