Sometime back we had to develop a rather scalable enterprise level Windows service. Creating a simple service is a cakewalk, deploying it for scalability is not. This article walks through how we combined Windows service and IIS together for a really good scalable deployment.
IIS gives us a large number of features which allow scalability, for example:
- Usage of application pools and their recycling
- Out of box scale out and load balancing
- Features like when the IIS worker process is using too much memory, a new worker process starts up leading to better performance
I could go on, but the point is that IIS has better scalability features than Windows services, simple things like multithreading and partitioning of execution space is provided by default. With little effort, we can develop solutions which work harmoniously across a server farm.
The trouble is that an IIS feature works when requested using an HTTP post. If we combine the best from both these worlds, we get a really great solution. That is what we try to do in this article.
For learning about how IIS provides scalability, please go to this link.
Windows services essentially execute some business logic over and over again after every time interval. The solution keeps this recurring logic in the Windows service while the business logic should be in a web or WCF service. Now this service can be called from the Windows service to do the job.
The Architecture of the Solution
Windows Server executing the service - This is a very simple Windows service whose sole purpose is to call a web service or WCF service at periodic intervals.
Load balancer - This may be a hardware or software based load balancer whose job is to distribute the request.
Servers executing business logic - These are servers which expose the service as a web / WCF service. The code is written in these to ensure scalability, some examples can be if we want to process records in a database or files on a server then this business logic will lock on a few records/files so that other competing servers may participate in the task. These servers should also be designed in such a manner that if the previous request is not completed, then new requests should not interfere with the previous request.
Some Sample Code
This is a very simple example in which every minute, we request the latest document dropped in the folder to be processed.
Timer timer = null;
protected override void OnStart(string args)
timer = new Timer(60 * 1000);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
OnStart event handler for the service is kicked in when the service starts. All we are doing is setting up our timer here.
When the timer is elapsed, we want to call the web service as in this code:
void timer_Elapsed(object sender, ElapsedEventArgs e)
ServiceReferenceProxy.ServiceSoapClient webServiceProxy =
It should be noted that to do this, we have used async operation on the web service method. This has been done so that if the task is not completed and the timer elapses again we get better scalability.
It should also be noted that we are not doing anything specific to get scalability on the Windows service end. The network load balancer will do it for us.
When the task of the web service is completed, we may choose to log or do some task this is done by the Completed event handler.
void webServiceProxy_DoSomeTaskCompleted(object sender, AsyncCompletedEventArgs e)
Setting Up Scalability Options
This section points out some reference material out on the net for setting up scalability:
- 25th October, 2009: Initial post