Scalable apps with Asynchronous Programming in ASP.NET
Do you want to know a secret? A deep, dark, dirty secret? One that, if revealed, would cause great angst in the ASP.NET community and prompt shouts of "Aha!" from the anti-Microsoft crowd?
Most Web sites built with ASP.NET aren't very scalable. They suffer a self-imposed glass ceiling that limits the number of requests they can process per second. These sites scale just fine until traffic rises to the level of this invisible ceiling. Then throughput begins to degrade. Soon after, requests start to fail, usually returning "Server unavailable" errors.
The underlying reason has been discussed many times in MSDN®Magazine. ASP.NET uses threads from a common language runtime (CLR) thread pool to process requests. As long as there are threads available in the thread pool, ASP.NET has no trouble dispatching incoming requests. But once the thread pool becomes saturated-that is, all the threads inside it are busy processing requests and no free threads remain-new requests have to wait for threads to become free. If the logjam becomes severe enough and the queue fills to capacity, ASP.NET throws up its hands and responds with a "Heck no!" to new requests.
One solution is to increase the maximum size of the thread pool, allowing more threads to be created. That's the course developers often take when their customers report repeated "Server unavailable" errors. Another common course of action is to throw hardware at the problem, adding more servers to the Web farm. But increasing the thread count-or the server count-doesn't solve the issue. It just provides temporary relief to what is in reality a design problem-not in ASP.NET itself, but in the implementation of the actual site. The real problem for apps that don't scale isn't lack of threads. It's inefficient use of the threads that are already there.