Thursday, August 2, 2007

Asynchronous Page Concept in ASP.NET

Server Unavailable.

This is the error most of us have faced without a clue asto what leads to this error and server being unavailable.Heres the reason:

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, i.e. 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 this error stating that Server is Unavailable.

SO whats the solution: Well the easiest way is to increase the maximum size of the thread pool, allowing more threads to be created. That's the course developers often take when repeated "Server unavailable" errors are reported. Another common course of action is 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 the problem.

One solution to this implemented in ASP.NET 2.0 is the use of ASYNCHRONOUS PAGES.

When ASP.NET receives a request for a page, it grabs a thread from a thread pool and assigns that request to the thread. A normal, or synchronous, page holds onto the thread for the duration of the request, preventing the thread from being used to process other requests. If a synchronous request becomes I/O bound—for example, if it calls out to a remote Web service or queries a remote database and waits for the call to come back—then the thread assigned to the request is stuck doing nothing until the call returns. That impedes scalability because the thread pool has a finite number of threads available. If all request-processing threads are blocked waiting for I/O operations to complete, additional requests get queued up waiting for threads to be free. At best, throughput decreases because requests wait longer to be processed. At worst, the queue fills up and ASP.NET fails subsequent requests with 503 "Server Unavailable" errors.

Asynchronous pages offer a neat solution to the problems caused by I/O-bound requests. Page processing begins on a thread-pool thread, but that thread is returned to the thread pool once an asynchronous I/O operation begins in response to a signal from ASP.NET. When the operation completes, ASP.NET grabs another thread from the thread pool and finishes processing the request. Scalability increases because thread-pool threads are used more efficiently. Threads that would otherwise be stuck waiting for I/O to complete can now be used to service other requests. The direct beneficiaries are requests that don't perform lengthy I/O operations and can therefore get in and out of the pipeline quickly. Long waits to get into the pipeline have a disproportionately negative impact on the performance of such requests

The concept of Asynchronous Pages is available only in ASP.NET 2.0 but it could be implemented in ASP.NET 1.x in a way outlined in the below mentioned link.

The trick here is to implement IHttpAsyncHandler in a page's codebehind class, prompting ASP.NET to process requests not by calling the page's IHttpHandler.ProcessRequest method, but by calling IHttpAsyncHandler.BeginProcessRequest instead.

ASP.NET 2.0 vastly simplifies the way you build asynchronous pages. You begin by including an Async="true" attribute in the page's @ Page directive, like so:

<%@ Page Async="true" ... %>

This property set to true, says the page to implement the IHttpAsyncHandler. Regarding this, you need to register the Begin method and End method of to the Page.AddOnPreRenderCompleteAsync.

// Register async methods
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler(EndAsyncOperation)

By these actions, the starts its normal life cycle, until the end of the OnPreRender event invocation. At this point the ASP.NET calls the Begin method that we registered earlier and the operation begins (calling the database etc...), meanwhile, the thread that has been assigned to the request goeas back to the thread pool. At the end of the Begin method, an IAsyncResult is being sent automatically to the ASP.NET and let it determine in the operation had completed, a new thread is being called from the thread pool and there is call to the End method (that we registered earlier, remmember?).

Jeff Prosise explains it all in

-- Ashutosh

No comments:

Post a Comment