Throttling in WCF
When your server is hosted out on the “big bad internet”, you need a way to make sure that you don’t get flooded with client requests. In WCF, our services support throttling as a way of mitigating potential DoS (denial of service) attacks. These throttles can also help you smooth load on your server and help enforce resource allocations. There are three service-level throttles that are controlled by ServiceThrottlingBehavior. These are in addition to any transport-specific throttles imposed by your binding. To fully understand the impact of these throttles you should also understand the threading/instancing characteristics of your service.
- MaxConcurrentCalls bounds the total number of simultaneous calls that we will process (default == 16). This is the only normalized throttle we have across all of the outstanding reads that the ServiceModel Dispatcher will perform on any channels it accepts. Each call corresponds to a Message received from the top of the server-side channel stack. If you set this high then you are saying that you have the resources to handle that many calls simultaneously. In practice how many calls will come in also depends on your ConcurrencyMode and InstancingMode.
- MaxConcurrentSessions bounds the total number of sessionful channels that we will accept (default == 10). When we hit this throttle then new channels will not be accepted/opened. Note that this throttle is effectively disabled for non-sessionful channels (such as default BasicHttpBinding).
With TCP and Pipes, we don’t ack the preamble until channel.Open() time. So if you see clients timing out waiting for a “preamble response”, then it’s possible that the target server has reached this throttle. By default your clients will wait a full minute (our default SendTimeout), and then time out with a busy server. Your stack will look something like:
TestFailed System.TimeoutException: The open operation did not complete within the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout.
[…]
at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreamble(IConnection connection, ArraySegment`1 preamble, TimeoutHelper& timeoutHelper)If instead you are timing out under channel.Send (rather than channel.Open), then it’s possible that you are hitting the MaxConcurrentCalls throttle (which kicks in per-message, not per-channel).
- MaxConcurrentInstances bounds the total number of instances created. This throttle provides added protection in the case that you have an instance lifetime that is not tied to a call or a session (in which case it would already be bounded by the other two throttles). Orcas durable services are one such scenario.
Net-net: if you are testing your services under load, and your clients start timing out, take a look at your throttling and instancing values. On the flip side, do not just blindly set these to int.MaxValue without fully understanding the potential DoS consequences.
August 9th, 2007 at 11:21 pm
Good info; decided to subscribe to your blog. Just wanted to let you know the indicated RSS Indigo link isn’t working, but the following does: http://kennyw.com/category/indigo/rss
October 8th, 2007 at 1:13 pm
Thanks for the head’s up. Bug in wordpress upgrade, should be fixed now.
November 22nd, 2007 at 1:48 pm
[…] verhoogd. Het is bijvoorbeeld een stuk lastiger om zo een DoS attack op je dak te krijgen (meer info). Dus zet de waarden ook weer niet te […]
December 20th, 2007 at 8:21 pm
Hi Kenny, is there a way to set a timeout on an operation?
I’ve got a WCF service, and I’ve set MaxConcurrentCalls to 4. If any individual call takes mroe than 15 seconds, I’d like WCF to kill it. The time I am interested in is once the call has started, and its processing on the server, how long it takes. I’m not interested in how long the client waited for the connection, or how long transmitting the datat took.
Is there a feature in WCF like that?
thanks!
- ALex
February 28th, 2008 at 1:25 am
Kenny,
I am seeing a weird behavior related to throttling and sessions that I was hoping you could explain to me. I am using the netTcpBinding, with the InstanceContextMode=Single and the ConcurrencyMode=Multiple. I hit the service with 20 simultaneous threads expecting to hit the default MaxConcurrentCalls throttle of 16, but instead I am hitting the MaxConcurrentSessions throttle of 10. Why is that when I am not using PerSession for my InstanceContextMode?
Thanks for the help,
-Scott
May 3rd, 2008 at 11:30 am
Alex, we don’t have a built-in feature to WCF like what you are asking for. You could start a timer within your service method though.
Scott, the reason you are hitting MaxConcurrentSessions is because each TCP channel is a session, and the MaxConcurrentSessions throttle applies to the channels being accepted. It’s independent of InstanceContextMode.
June 10th, 2008 at 10:41 am
[…] In addition, if the service throttling settings are not configured carefully for that service, a large number of requests will practically consume all the available resources (If that happens, the server will stop processing additional requests and you may run into a OutOfMemory exception as well). For more information about Service Throttling, I recommend this Kenny Wolf’s post. […]
July 16th, 2008 at 12:28 pm
Hi,
We are developping a service based application with WCF and experiencing the “MaxConcurrentSessions” issue
The problem is that in our case calls are asynchronous and the code is generated by the WCF Proxy Generator, any idea about how to safely close the proxy?
Thanks
Victor