One of my pet projects at the moment is building a personal productivity application called Smashing Pomodoros. I’m currently accepting registrations for a BETA launch at some point in the future. It is a labor of love because I ultimately want an application I am happy to use myself. However, I didn’t want to talk about Smashing Pomodoros specifically in this blog post, rather I wanted to talk about the fact that I am using Windows Azure Web Sites to host the application and a technique you can use to implement a background worker.
Before I get into the technical details, I wanted to provide some background (no-pun intended) on why this significant. When Windows Azure first went online Microsoft provided Cloud Services where a developer could divide their application up into web and worker roles. Web roles could be used to respond to HTTP requests, and worker roles could be used to perform long running and intensive operations. This web and worker compute model still persists in Windows Azure today and if you are running heavy background processing operations it is definitely worth a look.
That said, many web-sites have very light background processing requirements (like periodically sending out an e-mail to a user) and so that addition of a worker role to a Windows Azure deployment that might add up to as much as an extra $50-$100 in hosting charges wasn’t that appealing to many people. It turns out that in Windows Azure Cloud Services it is possible to provide worker role characteristics (a durable process that doesn’t start when IIS recycles) inside a web-role by injecting code in the WebRole class (derived from RoleEntryPoint) at the root of a Cloud Services web-project. This is a great way to save some costs when using Cloud Services and you only have a light background processing load.
More recently Microsoft has added Windows Azure Web Sites to their offering which increases the speed with which development teams can push out a new version of their application. The problem with Cloud Services (as opposed to Web Sites) is that each time you push out a new deployment to Cloud Services the underlying platform provisions a brand-new virtual machine. This can add 5-10 minutes to deployment times which can be painful for debugging and recovering from issues.
So Windows Azure Web Sites with sub-minute deployment times (for your typical basic web-application) has grown in popularity despite its preview status. The problem is there is no background worker capability built into Windows Azure Websites … or is there?
A Node.js Interlude
Initially you could only run Node.js on a Linux environment but it has since been extended to work on Mac OS X and more recently Windows! Individuals from Microsoft contributed to this effort in a number of ways, including the development of “iisnode” which is a module for IIS (the web-server built into Windows) which takes some of the pain out of hosting a Node application by wrapping it in some of the reliability features within IIS. Not long after this work was done iisnode got picked up by Windows Azure as well as other hosting providers who wanted to support Node on Windows.
Node.js is used in a number of places on Windows Azure, from Windows Azure Web Sites to Windows Azure Mobile Services and Microsoft have published an SDK specifically to support developers who want to work with Node.js. Getting started with Node.js on Windows Azure is easy, just following Microsoft’s instructions and you’ll have hello world running in no time.
Combining Node.js and ASP.NET
What some people may not realize is that it is possible to combine Node.js and ASP.NET in a single application running on Windows Azure Web Sites. By convention Windows Azure looks for a server.js (or similar) file in the root of the website. If it is present then it assumes that you want to use Node.js and it will do what it can to generate the appropriate configuration on the server side, all your code needs to do is to listen for requests forwarded on from iisnode which fronts the Node application.
However, running Node or ASP.NET are not mutually exclusive. Because all HTTP requests come through the standard HTTP.sys pipeline. It is possible to hive off your Node.js code into a seperate folder and then instruct iisnode to execute in that particular context.
The thing is that your Node application is just a standard node application so you can do all the usual things (provided you stay within your sandbox) that you would expect to be able to do, such as fire events in the background independent of whether there is a HTTP request in play.
Running a Background Worker with Node.js
Having set up your Windows Azure Web Site to support both Node.js and ASP.NET, you are now ready to use your Node application to perform background processing. This is something that Node excels at. All you need to do is set up a timeout that periodically takes some action, the code below is just a starting point that I have inside Smashing Pomodoros which returns some heartbeat information from the Node process.
When you first hit this code inside your application you’ll notice that the runtime value is null. This is because until you hit the application URL the hosting infrastructure doesn’t even bother spinning up the code. This can be a problem, but there are some workarounds.
Avoiding Idle Timeout
Some of the reliability features in IIS will actually make it difficult for you to implement any kind of background processing. Firstly, IIS is configured with an “idle timeout” where if your application does not receive a request with a specified period of time it will shutdown the application pool hosting your code, and in this case that includes the Node.js code. This makes sense in a heavily shared hosting environment you wouldn’t want one application spinning up consuming memory even when it isn’t servicing any requests. Unfortunately that doesn’t take into consideration any background processing that you want to perform.
One way to avoid idle timeout is ensure that your application is getting a steady stream of HTTP requests. You might be able to do this from the Node.js application itself but that doesn’t necessarily solve the problem of when your site is migrated to another server within the Azure Web Sites cluster and is yet to receive a request to kick things off.
To work around this you really need an external solution to hit the web-site and trigger Node.js to start. A recent addition to the Windows Azure Web Sites service offering is URL or endpoint monitoring. If you scale up your Windows Azure Website to a reserved instance you can specify an endpoint that you would like the monitoring infrastructure to hit every five minutes.
Using Windows Azure Mobile Services Scheduler Instead
The only issue that I see with WAMS is that unless you plan on using it for any kind of mobile device support it could be a bit of a sledge hammer just to get scheduling.
Summary and Hope
In this post I’ve shown a few tricks to try and get a level of background processing going within Windows Azure Web Sites, accepting that idle timeouts and application pool recycling means that you won’t be able to continuously execute code, despite being able to ensure it keeps running either via the new monitoring facilities or Windows Azure Mobile Services.
I really hope that Microsoft comes up with a lightweight scheduling/background worker option for Windows Azure Web Sites so that we don’t need this kind of trickery. Ultimately I think that this facility needs to be built into IIS itself so that developers can specify “jobs” in the web.config file that either run continuously or on a specified schedule. I would fully expect that in a Windows Azure hosting context this execution time would contribute to the CPU time against a Windows Azure Web Site.
Finally I strongly recommend checking out Windows Azure Mobile Services. I think that in the long run I think Windows Azure Mobile Services needs to be broken up into multiple components which can be mixed and matched. I would really love every web-site to have scheduler support without having to take on all of WAMS. For the time being though it is a nicely integrated set of services.
I hope this post helps. Enjoy your adventures with Windows Azure!