Wednesday, December 8, 2010

How to Combine a Worker and Web Role in Windows Azure

Some of us are running really small web sites on Windows Azure, and for every web site it seems that I needed to do a little background processing. Usually, this means creating both a web role to handle the web requests and a worker role to the background processing – typically through separate Visual Studio projects. However for a small web site this can get expensive if you are not fully utilizing the resources of both instances.

 

This article is going to show you how to include your background processing into your web role so you can fully utilize the Windows Azure instance. The same background processing that you would typically do in a worker role.

 

The recommended approach for Windows Azure is always run two instances to maximize uptime – if you were to follow the recommendation you would have the web role plus the extra background work running twice. Which means you need to design your background work to run Idempotency. For more information read: Idempotency for Windows Azure Message Queues.

The tasks that we are moving from the worker role will consume processing power and memory from the Windows Azure instance running the web role. The tasks will not block the web requests, they just share the resources of the instance. If you have a lot of background tasks or a lot of web requests, you should probably have separate worker and web roles in different instances.

 

An example of a background tasks that I want to include with my web site is a cleanup process for Session state that I blogged about here: Using SQL Azure for Session State, or creating a daily back-up of my SQL Azure database (something that I would do with SQL Server Agent if I was using an on-premise SQL Server). These tasks are not resource intensive – for the most part the work is being off loaded onto SQL Azure. However, at the same time I want them to be performed outside of the request/response cycle of the web role.

 

A Windows Azure web role is really a worker role with some IIS trim to handle HTTP requests. Every role in Windows Azure starts by calling the class that subclasses the RoleEntryPoint class. For a web role created by Visual Studio 2010 this look like this:

 

public class WebRole : RoleEntryPoint
{
    public override bool OnStart()
    {
        // For information on handling configuration changes
        // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.

        return base.OnStart();
    }
}

You can find this code in the file named Webrole.cs. You will also find that the Worker role has very similar code. The default worker role from Visual Studio also overrides the Run() method of the RoleEntryPoint like this:

 

public override void Run()
{
    // This is a sample worker implementation. Replace with your logic.
    Trace.WriteLine("WorkerRole1 entry point called", "Information");

    while (true)
    {
        Thread.Sleep(10000);
        Trace.WriteLine("Working", "Information");
    }
}

 

The easiest way to create a combined worker and web role is to create the web role first using Visual Studio 2010 and then override the Run() method. Here are the steps to do that:

  1. Open Visual Studio 2010
  2. Create a New Windows Azure Project

    clip_image002

  3. Choose ASP.NET MVC 2 Web Role or ASP.NET Web Role

    clip_image003

  4. After the files are created, file the WebRole.cs file and open it.
  5. Add this code to override the Run() method

     

    public override void Run()
    {
        // This is a sample worker implementation. Replace with your logic.
        Trace.WriteLine("WorkerRole1 entry point called", "Information");
    
        while (true)
        {
            Thread.Sleep(10000);
            Trace.WriteLine("Working", "Information");
        }
    }

     

  6. Add a using statement for these two assemblies: System.Diagnostics, System.Threading;
  7. Save and compile.

Now you have a combined worker and web roles for the price of one Windows Azure instance.

 

{6230289B-5BEE-409e-932A-2F01FA407A92}

10 comments:

  1. That is aweseome! I suspected as much when I decided to do a quick search on the topic -- very cool to find not only confirmation, but a well written post from someone who's done it. I was balking at the expense of a worker role instance until it really makes more sense. This is a great solution.

    ReplyDelete
    Replies
    1. One option is to specify the configuration in the ServiceConfiguration files and use CloudConfiguration class to read it.

      This also makes it easy to have separate configurations for local and cloud deployments.

      Delete
  2. Just be careful if you need to have configuration settings for your "Worker Role". The configurations settings in Web.Config are NOT accessible and a seperate App.Config does NOT get deployed automatically in that case...

    ReplyDelete
    Replies
    1. Further information on how to do this: http://stackoverflow.com/questions/12203765/combined-azure-web-role-and-worker-role-project-not-seeing-app-config-when-deplo

      Delete
  3. @kkarampelas, how did you solve this?

    ReplyDelete
  4. This is what I was looking for .... thanks indeed.

    ReplyDelete
  5. Many many thax for sharing this thax again

    ReplyDelete
  6. Hello,

    There is something i don't understand. wouldn't the IIS kill the thread running the worker role job, if there is not activity in the web role?
    for example, see that guy problem:
    http://forums.asp.net/t/1830688.aspx/1

    Thanks,
    Liran

    ReplyDelete
  7. Only works if you still host in Cloud Services....not saving any money

    ReplyDelete
  8. Linux Web Hosting at good rates for your own website. Choose from our unlimited personal and business packages for your linux web hosting. cpanel hosting

    ReplyDelete