Handling Cloud Service Role Configuration Changes in Windows Azure

September 29, 2013 — Leave a comment

Have you tried forcing an unexpected reboot?

Imagine a Worker Role that continuously polls a Windows Azure Storage Queue. It probably got it’s configuration settings when the Role instance started and it might not use the CloudConfigurationManager to refresh its configuration for every pull. This is where the Changing and Changed events come in. They allow you to build a strategy to deal efficiently with configuration changes.

Details

The Changing event and the Changed event are used together to identify and manage configuration changes to the service model. By using the Changing event, an instance can respond to a configuration change in one of the following ways:

  • Accept the configuration change while it is running, without going offline.

  • Set the Cancel property of RoleEnvironmentChangingEventArgs to true to take the instance offline, apply the configuration change, and then bring the instance back online.

By using the Cancel property, you can ensure that the instance proceeds through an orderly shutdown sequence and is taken offline before the configuration change is applied. During the shutdown process, Windows Azure raises the Stopping event, and then runs any code in the OnStop method.

You have a limited amount of time to accept or cancel the Changing event. Make sure your event handler can return in a timely manner.

You may want to cancel the Changing event if:

  • Your role instance does not support configuration changes while it is running, and requires recycling in order to apply the change.
  • Your role instance is performing work that should not be disrupted by a configuration change, and needs to proceed through the shutdown sequence before applying the change.

The RoleEnvironmentChangingEventArgs class provides a Changes property that returns a collection of the configuration changes that are about to be applied to the instance. Objects in this collection can be one of the following types:


The Code Example

In the following example, when the StorageAccount configuration changes, the instance would be taken offline, configuration changes would be applied, and it would be brought back online.

public class WorkerRole : RoleEntryPoint
{
    public override bool OnStart()
    {
        // Set the maximum number of concurrent connections
        ServicePointManager.DefaultConnectionLimit = 12;

        RoleEnvironment.Changing += RoleEnvironment_Changing;

        return base.OnStart();
    }

    void RoleEnvironment_Changing(object sender, RoleEnvironmentChangingEventArgs e)
    {
        var configurationChanges = e.Changes
                                    .OfType<RoleEnvironmentConfigurationSettingChange>()
                                    .ToList();
            
        if (!configurationChanges.Any()) return;

        if (configurationChanges.Any(c => c.ConfigurationSettingName == "StorageAccount"))
            e.Cancel = true;
    }

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

        var connectionString = CloudConfigurationManager.GetSetting("StorageAccount");
        var account = CloudStorageAccount.Parse(connectionString);

        var queueClient = account.CreateCloudQueueClient();
        var queue = queueClient.GetQueueReference("processing-queue");

        while (true)
        {
            var messages = queue.GetMessages(32).ToList();
            if (messages.Any())
                Process(messages);

            Thread.Sleep(10000);
            Trace.TraceInformation("Working", "Information");
        }
    }

    private void Process(IEnumerable<CloudQueueMessage> messages)
    {
        // TODO: Do something with each message
    }
}

In the following example, when the StorageAccount configuration changes, the Queue would be replaced by a Queue that would point to the new StorageAccount. This would be accomplished without taking the Role instance offline.

public class WorkerRole : RoleEntryPoint
{
    private CloudQueue queue;

    public override bool OnStart()
    {
        // Set the maximum number of concurrent connections
        ServicePointManager.DefaultConnectionLimit = 12;

        RoleEnvironment.Changing += RoleEnvironment_Changing;

        InitializeQueue();

        return base.OnStart();
    }

    void RoleEnvironment_Changing(object sender, RoleEnvironmentChangingEventArgs e)
    {
        var configurationChanges = e.Changes
                                    .OfType<RoleEnvironmentConfigurationSettingChange>()
                                    .ToList();
            
        if (!configurationChanges.Any()) return;

        if (configurationChanges.Any(c => c.ConfigurationSettingName == "StorageAccount"))
            InitializeQueue();
    }

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

        while (true)
        {
            var messages = queue.GetMessages(32).ToList();
            if (messages.Any())
                Process(messages);

            Thread.Sleep(10000);
            Trace.TraceInformation("Working", "Information");
        }
    }

    private void InitializeQueue()
    {
        var connectionString = CloudConfigurationManager.GetSetting("StorageAccount");
        var account = CloudStorageAccount.Parse(connectionString);

        var queueClient = account.CreateCloudQueueClient();
        queue = queueClient.GetQueueReference("processing-queue");
    }

    private void Process(IEnumerable<CloudQueueMessage> messages)
    {
        // TODO: Do something with each message
    }
}

References

About these ads

No Comments

Be the first to start the conversation!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s