IIS7で実行されているWCFサービス(* .svc)と、サービスをクエリしているさまざまなクライアントを持つアプリケーションがあります。サーバーはWin2008Serverを実行しています。クライアントは、Windows2008ServerまたはWindows2003サーバーのいずれかを実行しています。次の例外が発生しています。これは、実際には、多数の潜在的な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つにはパラメーターがなく、少しのデータを返します。もう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が接続を切断することから来ています。私が受け取る例外レポートは、ステップ3のタイムアウトからのものです。
これは、tcpストリーム「tcp.streameq192」を見て発見しました。次に、フィルターを「tcp.streameq192およびhttpおよびhttp.request.methodeqPOST」に拡張し、このストリーム中に6つのPOSTを確認しました。これは奇妙に思えたので、tcp.stream eq 100などの別のストリームで確認しました。3つのPOSTがありましたが、3回の呼び出しを行っているため、もう少し正常に見えます。ただし、すべてのWCF呼び出しの後に接続を閉じるので、ストリームごとに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ライブラリをもう一度見るように私をプッシュします。