Friday, November 28, 2008

Orcas SP1 Improvement: Asynchronous WCF HTTP Module/Handler for IIS7 for Better Server Scalability

Introduction

As mentioned in my last blog entry, for IIS-hosted WCF services, WCF holds the worker thread coming from ASP.NET until the whole request is completed to avoid a Denial of Service (DOS) attack. I also mentioned that on Windows 2008 Server, IIS7 has introduced the following registry setting to provide request throttling for all incoming requests:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\2.0.50727.0]

“MaxConcurrentRequestsPerCpu”=dword:0000000c

Based on this, in Orcas SP1 (.NET 3.5 SP1), WCF has implemented the asynchronous HTTP Module/Handler to allow better server scalability for high latency requests.

Asynchronous WCF HTTP Module/Handler

Besides the existing synchronous WCF HTTP Module/Handler types, WCF introduced the asynchronous versions. Together, WCF has the following four types implemented:

· Synchronous Module:

System.ServiceModel.Activation.HttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

· Asynchronous Module (new):

System.ServiceModel.Activation.ServiceHttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

· Synchronous Handler:

System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

· Asynchronous Handler (new):

System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Asynchronous HTTP Module

The new type ServiceHttpModule implements the System.Web.IHttpModule and it registers the async event HttpApplication.AddOnPostAuthenticateRequestAsync with a pair of async handlers:

static public IAsyncResult BeginProcessRequest(object sender, EventArgs e, AsyncCallback cb, object extraData)

static public void EndProcessRequest(IAsyncResult ar)

When a request comes in, WCF does some validation and returns from BeginProcessRequest immediately after passing the request up to internal processing logic. In this way, the worker process is immediately released.

If the service operation is asynchronous and it is waiting for slow I/O operations, the whole stack does not hold any thread. The only performance concern would be the memory usage to hold objects used to process the request. This allows many concurrent requests to be served by WCF without using a lot of threads and thus greatly improves the scalability of the service. This is very helpful when completing each request takes significant amount of time and many clients are served. In some private testing, WCF can easily support more than 10K concurrent slow requests, which is not possible with the synchronous HttpModule.

Asynchronous HTTP Handler Factory

You might have already noticed that WCF implements the Handler Factory instead of the asynchronous Handler directly. This allows more flexibility in the future to support different types of HTTP Handlers. The ServiceHttpHandlerFactory creates a stateless asynchronous HTTP handler of the following type which implements System.Web.IHttpAsyncHandler:

System.ServiceModel.Activation.ServiceHttpHandler

It implements the pair of asynchronous request handlers:

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)

public void EndProcessRequest(IAsyncResult result)

Default Installation – Synchronous Version

Though the asynchronous version of HTTP Module/Handler is added in this release, the default installation is still the synchronous version. Why is this?

First of all, you should not use asynchronous version of HTTP Module/Handler on Windows 2003 Server (with IIS6) without knowing the risk. If you have many clients, the service would be easily DOS attacked by too much memory usage due to huge amount of pending requests queued up in WCF transport layer without the throttling inside IIS/ASP.NET.

Because of the limitation on IIS6, WCF did not change the setup to switch to purely asynchronous due to the ramifications between IIS6 and IIS7 for this quick release. This means that in order to use the asynchronous version, you have to perform some manual registration.

Don’t worry, I have provided a private tool to do this registration for you.

WCF Module/Handler Registration Tool

You can find the simple tool called WcfAsyncWebUtil.exe attached in this blog. Here is the usage:

Usage: WcfAsyncWebUtil

Options:

/is

Install WCF Synchronous HTTP module and handler into IIS7 configuration

in Integrated Mode.

/ia

Install WCF Asynchronous HTTP module and handler into IIS7 configuration

in Integrated Mode.

/l

List WCF HTTP module and handler registered into IIS7 configuration in

Integrated Mode.

/t [ ]

Configure the throttling registry MaxConcurrentRequestsPerCpu for the ASP.NET

integrated pipeline to the value . Default is 100. This argument is

used together with /ia only

For example, if you want to register asynchronous HTTP Module/Handler with the ASP.NET throttling to be 1000, you can run the following command:

WcfAsyncWebUtil.exe /ia /t 1000

To list the installed WCF HTTP Module/Handler, you can run:

WcfAsyncWebUtil.exe /l

No comments: