1. ホーム
  2. wcf

[解決済み] WCFタイムアウト例外の詳細調査

2023-02-16 06:08:25

質問

IIS7 上で動作する WCF サービス (*.svc) と、そのサービスに問い合わせるさまざまなクライアントがあるアプリケーションがあります。サーバーは Win 2008 Server を実行しています。クライアントは、Windows 2008 Server または Windows 2003 Server を実行しています。次のような例外が発生します。これは、実際には多数の潜在的な WCF の問題に関連する可能性があることがわかりました。

System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.9320000. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The HTTP request to 'http://www.domain.com/WebServices/myservice.svc/gzip' has exceeded the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout. 

タイムアウトを30分に増やしましたが、エラーはまだ発生しています。データ量が多くてもアップロードやダウンロードに 30 分もかかることはないので、これは何か他の問題があることを物語っています。

エラーは出たり出なかったりです。現時点では、より頻繁に発生します。3 つのクライアントを同時に実行するか、100 のクライアントを実行するかは関係ないようで、それでも時々発生します。ほとんどの場合、タイムアウトは発生しませんが、それでも 1 時間に数回は発生します。エラーは、呼び出されたメソッドのいずれかから発生します。そのうちの1つのメソッドは、パラメータを持たず、ちょっとしたデータを返す。もう一つは、パラメータとして多くのデータを受け取りますが、非同期で実行されます。エラーは常にクライアントから発生し、スタックトレースでサーバー上のコードを参照することはありません。それは常にで終わります。

 at System.Net.HttpWebRequest.GetResponse()
  at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

サーバー上では 以下のようなバインディング設定を試してみました(現在)。

maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"

影響はないようです。

私は以下のスロットリング設定を試しました(現在も)。

<serviceThrottling maxConcurrentCalls="1500"   maxConcurrentInstances="1500"    maxConcurrentSessions="1500"/>

影響はないようです。

現在、WCFサービスに対して以下のような設定をしています。

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]

で実行したところ ConcurrencyMode.Multiple をしばらく実行してみましたが、やはりエラーは発生しました。

IIS を再起動し、基礎となる SQL Server を再起動し、マシンを再起動することを試みました。これらすべては影響を与えないようです。

Windows ファイアウォールを無効にしてみました。それは影響を与えないように思われます。

クライアントでは、以下の設定をしています。

maxReceivedMessageSize="2147483647"

<system.net>
    <connectionManagement>
    <add address="*" maxconnection="16"/>
</connectionManagement> 
</system.net>

クライアントが接続を閉じます。

var client = new MyClient();

try
{
    return client.GetConfigurationOptions();
}
finally
{
    client.Close();
}

より多くの発信接続を許可するようにレジストリの設定を変更しました。

MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.

私は今ちょうど最近、SvcTraceViewer.exe を試しました。私は、クライアント側で 1 つの例外をキャッチすることができました。その持続時間は 1 分であることがわかります。サーバー側のトレースを見ると、サーバーはこの例外を認識していないことがわかります。私が見ることができる最大の持続期間は10秒です。

を使用してアクティブなデータベース接続を調べました。 exec sp_who を使用してアクティブなデータベース接続を調べました。ほんの少し (2-3) しかありません。TCPviewを使用して、1つのクライアントからのTCP接続を調べました。通常2-3程度で、最大で5または6を見たことがあります。

簡単に言えば、私は困っています。私が見つけることができるすべてを試してみましたが、WCF の専門家が見ることができるような非常に単純な何かを見逃しているに違いありません。サーバーが実際にメッセージを受信する前に、何かが低レベル (TCP) で私のクライアントをブロックしているか、または何かがサーバー レベルでメッセージをキューに入れ、決して処理させないようにしていると、私は直感的に思います。

もし、私が見るべきパフォーマンス カウンターがあれば、教えてください。(これらのカウンターのいくつかは解読するのが難しいので、どの値が悪いかを示してください)。また、どのように WCF メッセージ サイズを記録することができますか。最後に、(私のアプリケーションから独立して)クライアントとサーバーの間に確立できる接続数をテストすることができるツールはありますか?

お時間をいただきありがとうございました。

6月20日追加情報です。

私のWCFアプリケーションは、以下のようなことをしています。

while (true)
{
   Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
   Step2GetWorkUnitFromServerViaWCF();
   DoWorkLocally(); // takes 5-15minutes. 
   Step3SendBackResultsToServerViaWCF();
}

WireShark を使用して、エラーが発生したときに、5 回の TCP 再送があり、その後 TCP リセットがあることを確認しました。私の推測では、RST は WCF が接続を切断したことに起因しています。私が受け取った例外レポートは、Step3がタイムアウトしたことによるものです。

私は、tcp ストリーム "tcp.stream eq 192" を見ることによって、これを発見しました。次に、フィルターを "tcp.stream eq 192 および http および http.request.method eq POST" に拡張し、このストリーム中に 6 つの POST があることを確認しました。これは奇妙に思えたので、tcp.stream eq 100 などの別のストリームで確認しました。私は3回のPOSTを行いましたが、これは3回の呼び出しを行うため、もう少し正常なように思われます。しかし、私はすべてのWCF呼び出しの後に接続を閉じているので、私は1つのストリームに1つの呼び出しを期待していました(しかし、私はTCPについてあまり知りません)。

もう少し調査して、私はhttpパケットのロードをディスクにダンプして、これらの6つのコールがどこにあるかを見てみました。

1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2

私の推測では、2つの同時実行クライアントが同じ接続を使用しており、それが重複を見た理由です。しかし、私にはまだ理解できない問題がいくつかあります。

a) なぜパケットは破損しているのでしょうか? ランダムなネットワークの偶然の産物でしょうか? 負荷は、このサンプル コードを使用して gzip されます。 http://msdn.microsoft.com/en-us/library/ms751458.aspx - このコードは、同時に使用すると、時々バグが発生する可能性がありますか?gzip ライブラリなしでテストすべきですね。

b) なぜ、破損した操作がタイムアウトした後に、ステップ1 & ステップ2が実行されるのを見ることができるのでしょうか? これらの操作は発生しないはずのように私には思えます。私の TCP 理解に欠陥があるため、正しいストリームを見ていないのかもしれません。私は、同時に発生する他のストリームを持っています。他のストリームを調査すべきです。ストリーム190-194をざっと見たところ、Step3のPOSTは適切なペイロードデータを持っている(破損していない)ことがわかります。gzip ライブラリをもう一度見てみるよう、私に促しています。

どのように解決するのですか?

.Netクライアントを使用している場合、.Netクライアントに設定されていない可能性があります。

//This says how many outgoing connection you can make to a single endpoint. Default Value is 2
System.Net.ServicePointManager.DefaultConnectionLimit = 200;

元の質問と回答はこちら WCFサービススロットリング

更新 :

この設定は、.Netクライアントアプリケーションの起動時や、テストを開始する前に行うことができます。

さらに、以下のようにapp.configファイルにも記述することができます。

<system.net>
    <connectionManagement>
      <add maxconnection = "200" address ="*" />
    </connectionManagement>
  </system.net>