I am writing in order to ask a question on WCF performance.
1. Background
We have a client-server system that runs on .NET 3.5. The server is a C# service and the client is a silverlight app.
I have written a stress tester that is a winforms app and works like that:
[eg for (i=0;i<100;i++)
Send(payload)]
[ServiceBehavior(InstanceContextMode
=InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
.serviceThrottling:
maxConcurrentSessions="200"
2. The Issue
After some thresholds(dependent on the stress test loads and the environment under test) my worker processes (normal .NET 3.5 C# console apps) begin to throw exceptions. I was getting timeoutExceptions initially but after a lot of read & tweak sessions I got to a point where I get only two exceptions (only under very high load)
Alongside with that I can see substantial message loss. The server never fails(which is good). I think the server is simply rejecting messages it cannot handle.
3. Actions Taken
I have read a lot of articles and tweaked a lot of parameters(including throttling, timeouts, etc). For example I have tried all of the sugggestions here: http://www.codeproject.com/KB/WCF/WCFThrottling.aspx
I do get performance improvement but depending on what environment I am running the server I will hit this upper limit and start having messages rejected.
No errors at all are reported in the trace logs
4. Ideally...
...I would want to have a server that gets slower as load increases, but does not miss messages. (ie its ok if a client takes 10 secs to get a reply if 500 others are using the service)
Is this possible under WCF over Http and a single-threaded, single context servive? Am I missing a setting here or am I hitting an upper bound and getting the expected WCF behaviour?
NB: I have tried using ConcurrencyMode.Multiple
. I do get an improvement (ie more load is needed to hit the upper bound) but I do hit the same exceptions.
I guess I 'found' my answer!
I will explain here what I did in case someone else bumps into this one.
First of all you can check the Calls Oustanding counter, which is something like a T*CP backlog*.
In addition in perfmon can see how many calls are being handled concurrently, and how many are queued.
These two indicators allowed me to validate that indeed I was hitting the roof. Therefore I needed code that would send/rcv some ACKs upon messaging. Luckily MS have already done this for us! Its called reliable WCF messaging.
http://msdn.microsoft.com/en-us/library/ms730123.aspx http://msdn.microsoft.com/en-us/library/aa480191.aspx
By implementing a WsHttpBinding the server could cope under loads where it previously failed. In addition the server managed to cope with loads twice as much as before.
Clearly there is a performance overhead but it is indeed reliable.
Great, so I guess that now that I found the solution I can tell to the users that all of that fantastic stuff is out there, but they ain't gonna get nothing of this because their client runs on silverlight 3 which does not have reliable WCF implementations...yey!