I have a fairly simple WCF web sevice, hosted in IIS Express (eventually to be full IIS) using .Net 3.5. The service method is fairly uninteresting.
[ServiceContract]
public class MySvc
{
[OperationContract]
public Stuff MyMethod(string input)
{
Stuff result = DoSomething();
return result;
}
}
The service configuration is also fairly generic:
<system.serviceModel>
<services>
<service behaviorConfiguration="MySvcBehavior" name="MySvc">
<endpoint address="" binding="wsHttpBinding" contract="MySvc">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MySvcBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
The service is consumed by a code-behind in an ASPX application. There's a service reference, leading to some equally uninteresting code.
MySvcClient svc = new MySvcClient();
Stuff result = svc.MyMethod("foo");
As long as it's one request at a time, everything works just fine and the client code gets the expected result. Yay.
The problem comes when I do some very primitive stress testing. I load the client ASPX page in a browser, and then hold down the F5 key. Watching the IIS Express window, at first the results come back as status 200, but after a few minutes I start seeing status 500. At this point, the service will only respond with status 500 until I restart IIS Express. (Based on waiting about 10 minutes.)
Setting a breakpoint in the client code, I see the full return message is "There are too many pending secure conversations on the server. Please retry later."
Setting a breakpoint in the server code, I find that my code isn't even being invoked. So it's failing somewhere between the call and the actual start of my code.
My online searches haven't been very promising, mostly leading to the same suggestion of writing a custom binding in order to override the maxPendingSessions property and a thread starting with "Someone told me there's a [unnamed] config file setting" which then leads to a broken link claiming Microsoft has acknowledged this as a bug.
The link about the maxPendingSessions property does mention a limit of 128 connections with a timeout of two minutes, and I can certainly see where my method of testing is going to interrupt some connections. Is this the expected result of an admittedly bad testing methodology? Or can something be done in the configuration to improve this?
Sounds like you have a zillion open connections on the server - due to the client side not using a 'using' for the connection.
I would first suggest testing this on full IIS on a server class machine. I wouldn't trust IIS Express on a client OS for performance testing.
If it is still bad then look at throttling to restrict maxConcurrentCalls. http://msdn.microsoft.com/en-us/library/vstudio/ms735114(v=vs.90).aspx
To those recommending a using statement: You should NOT use a using statement to close clients.
See http://msdn.microsoft.com/en-us/library/aa355056.aspx
Instead to close clients you should use the following snippet:
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
Or simply a vanilla catch if you prefer not to cache explicit exceptions. Sometimes you'd want to catch explicit exceptions because if the communication object is not faulted you can retry your operation which offers best use of resources.
To your issue of pending conversations on the server, this will become less common once you close your client correctly, however you may still see it if your server side code has a long running operation and clients are queuing up. In this case, to increase the value of MaxPendingChannels you either have to use a custom binding in both the client and receiver side config files, or programmatically modify the binding on the receiver side before you start the service. The default value of MaxPendingChannels is actually 4 if you are using .NET 3.5. The value is purported to be 128 for .NET 3.0. Both are low in my opinion.
See http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/745b95d2-1480-4618-89f5-1339d6ee228d
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With