C# 4.0 (すぐには 4.5 にアップグレードできません) と WCF を使用しています。私はサーバーを制御しておらず、使用されているコードやテクノロジーを見ることができないことに注意してください。この問題は、さまざまな人が作成したさまざまなサーバーで発生します。
サーバーごとに 1 つずつ、多くのサーバー (10 としましょう) にできるだけ多くの要求を送信します。1 秒あたり 2 ~ 30 のリクエストが発生します。30 秒から 5 分の間に、 TimeoutException が発生します。
exception {"The HTTP request to 'http://xx.xx.xx.xx/service/test_service' has exceeded the allotted timeout of 00:02:10. The time allotted to this operation may have been a portion of a longer timeout."} System.Exception {System.TimeoutException}.
Stack Trace :
Server stack trace:
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeEndService(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)
at Device.EndTest(IAsyncResult result)
at DeviceClient.EndTest(IAsyncResult result) in ...
at TestAsync(IAsyncResult ar) in ...
InnerException は次のとおりです。
[System.Net.WebException] {"The request was aborted: The request was canceled."} System.Net.WebException
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
Wireshark は、接続を開いていない (SYN がない) ことを教えてくれます。したがって、これはクライアントの問題である必要があります。TCPView に多くの TIME_WAIT 接続があります
同期呼び出しの使用は機能していますが、不可能です。
次のコード例では、サーバーごとに 1 つのメソッド呼び出しがあることに注意してください。(私の場合、10個の同時TestAsync)
(実際のプロジェクトでは、セマフォの代わりに CCR を使用しますが、結果は同じです)
private void AsyncTest()
{
//GetServiceObject Will add custom bindings and more..
Client client = ClientBuilder.GetServiceObject();
while (true)
{
Semaphore semaphore = new Semaphore(0,1);
client.BeginTest(BeginTestCallback, new AsyncState
{
Client = client,
Semaphore = semaphore
});
semaphore.WaitOne();
}
}
private void BeginTestCallback(IAsyncResult asyncResult)
{
try
{
AsyncState state = asyncResult.AsyncState as AsyncState;
Client client = state.Client;
Semaphore semaphore = state.Semaphore;
Client.EndTest(asyncResult);
semaphore.Release();
}
catch (Exception e)
{
//Will catch the exception here because of Client.EndTest(asyncResult)
Debug.Assert(false, e.Message);
}
}
で試しました
ServicePointManager.DefaultConnectionLimit = 200;
ServicePointManager.MaxServicePointIdleTime = 2000;
いくつかの投稿が示唆したように、成功しませんでした。
オープン、送信、受信、クローズのタイムアウトを本当に高く設定しても、同じ例外が発生します。WCF は、リクエストの送信時に「スタック」しているようです。サーバーは引き続き他の要求に正しく応答します。
アイデアはありますか?
また、これを行うと (while(true) の代わりに Callback で BeginTest を実行)、例外が発生することはありません?!?!
private void AsyncTest()
{
//GetServiceObject Will add custom bindings and more..
Client client = ClientBuilder.GetServiceObject();
try
{
client.BeginTest(BeginTestCallback, new AsyncState
{
Client = client
});
}
catch (Exception e)
{
Debug.Assert(false, e.Message);
}
}
private void BeginTestCallback(IAsyncResult asyncResult)
{
try
{
AsyncState state = asyncResult.AsyncState as AsyncState;
state.Client.EndTest(asyncResult);
state.Client.BeginTest(BeginTestCallback, state);
}
catch (Exception e)
{
//No Exception here
Debug.Assert(false, e.Message);
}
}