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つはパラメーターを持たず、データのビットを返します。もう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がありました。ただし、すべての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ライブラリを見るように促します。