10

でホストされているサービスWPFを介してデータを要求しているクライアントがいます。サービス メソッドは、データを取得するためにストアド プロシージャ ( ) を呼び出します。WCFIIS 7SQL 2012EF

ロードするデータが大量にあるため、クライアントは、データのロードを「分割」して大きなペイロードとタイムアウトを回避するために、サービス メソッドを複数回呼び出します。

生成されたサービス プロキシを使用します。System.ServiceModel.ClientBase<T>.

また、バイナリ エンコーディングを使用したカスタム http バインディングも使用しています (ここから)。実際の実装は次のとおりです。

<customBinding>
   <binding name="CustomBinding_IPointDataAccess" closeTimeout="00:01:00"
      openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
      <binaryMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" maxSessionSize="2048">
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="16384" />
      </binaryMessageEncoding>
      <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
         maxReceivedMessageSize="2147483647" allowCookies="false" authenticationScheme="Anonymous" bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard" keepAliveEnabled="true" maxBufferSize="2147483647" proxyAuthenticationScheme="Anonymous" realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false" useDefaultWebProxy="true" />
   </binding>

また、IIS では動的圧縮がオンになっています。Fiddler でリクエストを表示できます。メッセージの本文のサイズは問題なく (~50KB) 、リクエストの 99% は 1 ~ 2 秒で返されます。完全!

ただし、ほとんどすべての反復で、完了するまでに数分かかる呼び出しが 1 つあります。その理由はわかりません...sendTimeOutクライアントでの私の呼び出しは 1 分で、当然その 1 つの呼び出しは失敗します。私はそれを 10 分に延長しました。通話は 2 分強で完了するように見えますが、場合によってはそれ以上かかることもあります。問題は非常にランダムに発生します。最初の呼び出しである可能性もあれば、30 回目の呼び出しである可能性もあります。しかし、それは非常に再現性があります。

WCF サービス メソッドのストアド プロシージャ呼び出しの周りにログを配置し、実行して 1 秒以内にデータを取得しました。したがって、データベースの問題ではないと思います。

Fiddler を使用すると、問題のある呼び出しによって次のような出力が生成されます。

ACTUAL PERFORMANCE
--------------
ClientConnected:     14:02:42.959
ClientBeginRequest:  14:03:01.224
GotRequestHeaders:   14:03:01.224
ClientDoneRequest:   14:03:01.574
Determine Gateway:   0ms
DNS Lookup:      0ms
TCP/IP Connect:  46ms
HTTPS Handshake:     0ms
ServerConnected:     14:05:16.021
FiddlerBeginRequest: 14:05:16.021
ServerGotRequest:    14:05:16.021
ServerBeginResponse: 14:03:04.784
GotResponseHeaders:  14:05:16.561
ServerDoneResponse:  14:05:16.611
ClientBeginResponse: 14:05:16.611
ClientDoneResponse:  14:05:16.611

ServerBeginResponseとの間のかなりの時間に注意してくださいGotResponseHeadersこれは、ここで見られる問題と非常によく似ているようです。

私は WCF Service Tracing を有効にしました。一見すると、エラーや警告はありませんが、基本を超えて見ているものをあまり理解できません。

問題の内容と場所を突き止めるにはどうすればよいですか? シリーズ化ですか?ネットワークの問題ですか?サーバーは、クライアントが送信する大量のリクエストに対応できませんか?

適切な を追加して、構成ファイルの WCF Throttling を調整しようとしましたserviceBehaviorsが、違いはありませんでした。

私は VPN 接続を介してこれを行っていることに言及する必要がありますが、ファイル転送、リモート デスクトップ接続などの他のことは問題なく機能します。かなり信頼できそうです。

必要に応じて詳細を提供できます。

編集 (6.10.2013):これが関連しているのか、単なるまぐれなのかはわかりませんが、問題のある呼び出しで、ボディのサイズが他のものよりも大幅に小さいことに気付きました。これは毎回ではありませんが、いくつかの手がかりが得られる場合があります。以下は、Fiddler からのスクリーン キャプチャで、呼び出しごとにボディ サイズがどの程度一貫していなければならないかを示しています。選択したエントリ (#21) は、サイズが他のエントリよりもはるかに小さいですが、完了するまでに 2 分以上かかります。

ここに画像の説明を入力

奇妙なことに、今回は例外が発生しました。例外は毎回発生しません。

System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.

Server stack trace: 
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
4

2 に答える 2

5

コメントで提案したように、transfermode を streamed に設定して、これがメモリ不足に関連する問題である可能性を排除してみてください (ストリーム モードでは wcf が使用するメモリが少なくなるはずなので)。

この問題を見たとき、これが問題である可能性があると思われました。これは、多くのサービス呼び出しを立て続けに行ったときにのみ発生するように思われるためです。私の経験では、これは多くの場合、プロキシがクライアントから適切に閉じられていないか、サーバーがメモリ不足のために GC を実行しているという 2 つの問題のうちの 1 つです。

transfermode がバッファリングされると、WCF はメッセージ応答のデータセット全体をメモリにロードしてから、クライアントに送り返します。Streamed は、バッファリングせずにデータを送り返すだけです。大きなデータ セットの場合ははるかに速く、小さなデータ セットの場合はわずかに遅くなる傾向があり、(サーバーとクライアントの両方で) 使用するメモリは常に少なくなります。

于 2013-06-10T19:09:43.203 に答える
2

タイムアウトの原因を突き止めるには、WCF で何が起こっているかを追跡する必要があります。以下を構成ファイルに追加すると、クライアントとサーバーにトレース ファイルが生成されます。

<system.diagnostics>
   <sources>
       <source name="UserTraceSource" switchValue="Warning, ActivityTracing" >
          <listeners>
              <add name="xml"
                 type="System.Diagnostics.XmlWriterTraceListener"
                 initializeData="C:\logs\UserTraces.svclog" />
          </listeners>
       </source>
   </sources>
   <trace autoflush="true" /> 
</system.diagnostics>

通常、ファイルは何が起こっていて何が失敗したかを正確に教えてくれます。C:\logs ディレクトリがあり、ユーザーがディレクトリに対する書き込み権限を持っていることを確認してください。

wcf トレースを構成する

于 2013-06-10T15:26:05.700 に答える