



One of the things you have to consider in any application is configuration. In windows and web forms we have *.config files to help configure our application prior to start. They are a useful place to store things like provider configuration, IOC container configuration, connection strings, service end points, etc. Let’s face it – we use configuration files a lot.
In this article I will discuss the different types of configuration available to you, how they can be leveraged in your application, and how configuration items can be changed at runtime without causing your application roles to restart.
In Windows Azure applications, configuration can work exactly the same as standard .Net applications. If you have a web role, then you have a web.config. And if you have a worker role, you get an app.config. This allows you to provide configuration information to your role when it starts.
But what about configuration values you want to change after your app is deployed and running? It certainly is a lot harder to get in and change a few angle brackets in your web.config after it is deployed to production in the cloud. Do you really want to have to upload a whole new version of the app package with the new web.config file in it?
Or what about being able to change configuration aspects of all your running instances in one go, and not having to stop them from running to do so? Why should a configuration change necessitate a restart, such as is needed with web.config and app.config files?
In Windows Azure we have a new method of configuring our roles that gives us flexibility and consistency in our applications.
In Windows Azure we can get the above benefits of flexibility and consistency in our configuration, via the service configuration file: ServiceConfiguration.cscfg.
This file contains information about your app that can be used at start-up, and can be changed at runtime without requiring a new package upload. This includes the number of running instances, certificate information, and specific application configuration settings, such as connection strings, port numbers, REST endpoints, etc.
The service configuration works in partnership with the service definition file: ServiceDefinition.csdef.
Both files are located in your main cloud project. The service definition is the “boss”. It can not be changed at run time. When you upload your Azure application, the service configuration is part of the application package, but the service definition is uploaded separately. This is because the service definition contains all the instructions about how an application should be deployed including: details about each of the roles, what their fault and upgrade domains are, TCP ports to open (for worker roles), what local storage should be available, VM size to use, level of trust, and more. After upload, the service definition is shipped off to the fabric controller who will parse it and work out what to do with your cloud package.
We’ll focus on one more thing you will find in the service definition file – information about configuration items. Essentially the service definition states what configuration values will be available in the service configuration file, for each role. It looks something like this:
1: <WorkerRole name="ImageSearch.Cloud.Overlord">
2: <ConfigurationSettings>
3: <Setting name="ImageSearchSettings" />
4: <Setting name="ImageSearchDBC" />
5: <Setting name="SearchMultiplier" />
6: <Setting name="MatchTolerance" />
7: </ConfigurationSettings>
8: </WorkerRole>
If a configuration setting name is not specified in the service definition, it can not be used in the service configuration file to configure your app. Think of it as an instruction to the fabric controller: “My app can be configured with these 4 values”. Also, once you’ve uploaded your application, you can’t add or remove settings, since the service definition file is not editable; you can only change the configuration values. I’ll show you how later on.
In the service configuration file, our entry would look like this:
1: <Role name="ImageSearch.Cloud.Overlord">
2: <Instances count="1" />
3: <ConfigurationSettings>
4: <Setting name="ImageSearchSettings" value="UseDevelopmentStorage=true" />
5: <Setting name="ImageSearchDBC" value="Data Source=..." />
6: <Setting name="SearchMultiplier" value="3" />
7: <Setting name="MatchTolerance" value="50" />
8: </ConfigurationSettings>
9: </Role>
Its pretty similar to the <appSettings> element you are probably familiar with. There is an element for every role in your cloud project, and the <ConfigurationSettings> child element contains all the settings of your application as “name/value” pairs.
When setting values in the service configuration and definition files directly, you will get complete intellisense, making it very easy to work out what the appropriate values are. It is also possible to set configuration values via the tooling.
In your main cloud project (which contains the links to all your roles) you can bring up the properties window for a role. Under the ‘Settings’ tab you can add new configuration values.
When adding a new setting, the IDE will insert the relevant placeholder in the service definition, and insert the value in the service configuration. This makes the Visual Studio IDE approach a bit of a time saver and helps ensure your definition and configuration files are in sync. In the above screen shot you can see we have two configuration items: the first is a cloud storage connection string, while the second is a database connection string. Essentially, all configuration items are strings, but the IDE gives you some shortcuts when creating configuration values for storage accounts via this connection string type. Clicking the ellipses […] delivers a new modal window where you can specify the details of your storage account.
In the end this just creates another string configuration value that can be used by the app.
<Setting
name="ImageSearchSettings"
value="DefaultEndpointsProtocol=https;AccountName=ImageSearch;AccountKey=3ob...UY=="
/>
The simplest way to leverage configuration items in your code is to use the API that comes with the Cloud tools. This provides a bunch of useful assemblies that give you strongly typed access to all the things you would want to do with your application. In the Microsoft.WindowsAzure.ServiceRuntime assembly (and namespace) we have a sealed class called RoleEnvironment which affords us a static method for accessing configuration values at runtime:
var tolerance = RoleEnvironment.GetConfigurationSettingValue("MatchTolerance”);
1: public class StorageAccountFactory
2: {
3: public static CloudStorageAccount Create()
4: {
5: return CloudStorageAccount.FromConfigurationSetting("ImageSearchSettings");
6: }
7: }
SetConfigurationSettingPublisher needs to be called before FromConfigurationSetting can be used
What this is trying to tell you is that you need to instruct the CloudStorageAccount to use the standard configuration definition file when loading configuration settings. That might seem a little silly at first.. where else could your configuration settings be coming from? Haven’t you just wasted half an hour reading about the Azure configuration files?
Well when running your app in Azure, your configuration will certainly come from the Azure service configuration file. But the tooling guys at Microsoft wanted you to create apps that could still be easily switched back to running on private infrastructure without having to remove all the Azure related integration points; and unfortunately the service configuration file is an Azure only integration point. We need to be able to factor that out into abstraction and make our apps transparent to the source of configuration settings.
Let me explain further with an example. Consider this scenario: you have a web role that puts items into a queue, and a worker role that grabs items out of the queue and processes them. You have your web role setup to use CloudStorageAccount.FromConfigurationSetting to load your storage client from the service configuration file. However later on you decide to move your web role on premise, and leave the other bits running in Azure. You detach your web role from the cloud service project; it now stands on its own two feet and can be run on IIS. But that also means you no longer have a service configuration file; you’re stuck with plain old web.config again. Ideally you should still be able to use the same static method to load your storage account from configuration settings, its just that those configuration settings are now in a different place.
The SetConfigurationSettingsPublisher method that the error refers to is another static method on the CloudStorageAccount class that lets us specify where configuration should be loaded from. According to the MSDN documentation:
This method should be called once to set up the environment. The environment could be the Windows Azure runtime, in which case the publisher is a simple wrapper of the configuration reading and change event. The environment could also be a .NET environment, in which case the developer can hook up a custom configuration reader and change notification.
As stated in the documentation, you should only setup the configuration publisher once, so this ideally should happen in your role’s OnStart event. The code to tell CloudStorageAccount to use the configuration definition uses a delegate which is stored and called every time the configuration is requested:
1: CloudStorageAccount.SetConfigurationSettingPublisher(
2: (configName, configSetter) =>
3: configSetter(RoleEnvironment.GetConfigurationSettingValue(configName))
4: );
In essence, a configuration setting publisher is just an Action – a delegate that is called when attempting to get the value of a configuration setting name. In the code above we are telling the storage account client that whenever it needs to get a configuration item (configName) then call the standard RoleEnvironment.GetConfigurationSettingValue static method with that name to find and return the value.
Great question! Lets say we actually wanted to make our code more flexible and be able to switch between the configuration definition when running in Azure, over to web.config appSettings when running in plain old IIS on our own server. We would like our app to detect that it is no longer running in the world of Azure, and there is a property we can use that does just that: RoleEnvironment.IsAvailable. We can use it to customise who our setting publisher is. Consider the following static method on a factory class that I have created called StorageAccountFactory:
1: public static Action<string, Func<string,bool>> GetConfigurationSettingPublisher()
2: {
3: if (RoleEnvironment.IsAvailable)
4: return (configName, configSetter)
5: => configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
6:
7: return (configName, configSetter)
8: => configSetter(ConfigurationManager.AppSettings[configName]);
9: }
You would then call the new method like this:
1: CloudStorageAccount.SetConfigurationSettingPublisher(
2: StorageAccountFactory.GetConfigurationSettingPublisher()
3: );
Walla! Our app is now aware of when it is and is not running in Azure and can switch its settings provider as needed, while still giving us the benefit of using the CloudStorageAccount API to load our storage account from configuration.
As I mentioned earlier, you can change configuration values at runtime while your app is already strolling along happily in production. The reasons for needing to make a change can vary; perhaps you want to tweak a performance setting or change the format of log file output.
Most importantly, you don’t want your app to always stop and restart on a configuration change. The default behaviour of Azure roles is to restart on any configuration change so if you want to prevent this behaviour, read on!
You can detect changes to the role environment by handling the 2 following static evenst, available on the RoleEnvironment class:
RoleEnvironment.Changing += RoleEnvironmentChanging;
RoleEnvironment.Changed += RoleEnvironmentChanged;
When you create a new web or worker role, the first event is automatically inserted for you, along with the event handler code:
1: private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
2: {
3: if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange))
4: {
5: e.Cancel = true;
6: }
7: }
The default behaviour of this code is to ‘cancel’ the event on any configuration change. Cancelling the event is a bit misleading; what this actually means is that the role will be recycled, configuration changes will be applied, and the role will start up again. So “e.Cancel” actually means “e.Reboot”.
Naturally we need to make changes to this default code. Its up to you to decide which changes require the role to restart and which ones don’t. Personally, I like to make a static array of names of configuration items that I don’t want to cause a restart, like so:
private static readonly string[] ExemptConfigurationItems = new[] { "MatchTolerance", "SearchMultiplier" };
Then in the RoleEnvironmentChanging event handler we can decide whether or not to reboot, and if we don’t need to reboot, apply the new configuration changes in the RoleEnvironmentChanged event:
1: private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
2: {
3: Func<RoleEnvironmentConfigurationSettingChange, bool> changeIsExempt =
4: x => !ExemptConfigurationItems.Contains(x.ConfigurationSettingName);
5:
6: var environmentChanges = e.Changes
7: .OfType<RoleEnvironmentConfigurationSettingChange>();
8: e.Cancel = environmentChanges.Any(changeIsExempt);
9:
10: if (!e.Cancel)
11: {
12: var oldMultiplier = RoleEnvironment
13: .GetConfigurationSettingValue("SearchMultiplier");
14: }
15: }
The RoleEnvironmentChangingEventArgs supplies a Changes property which is a list of all changes that caused this event to fire. Typically these will be a change of the number of instances that the role is running, or a change to configuration items. We request all the changes that are of type RoleEnvironmentConfigurationSettingChange which represents just setting changes. We then compare the changed items to our static list of configuration names, and if any of the changes aren’t in the list, we’ll do a reboot. If we don’t do a reboot (which means all changes belonged to our exempt list) we will apply those new changes as necessary.
And that’s all there is to know about configuration at this point in time. Here’s a couple of points summarising what we’ve learnt:
Please keep in mind that this was valid at the time of writing and that the Azure platform is continually evolving, so there might already be a better technique for what you want to do.










More Options ...

Categories
Tag Cloud
Blog RSS
Comments RSS

Void
Life
Earth
Wind « Default
Water
Fire
Light 
8:18 am - March 11th, 2010
Thanks for this info – I tried this in my Worker role to allow for changes in debugging switches without recycling the role. When I do a
csrun /update:169;ServiceConfiguration.cscfg to simulate a change in the configuration in the cloud fabric (after I change an entry in the config file), I see the code correctly go through and set e.cancel to false, but I still see Azure tear down the role.
Here’s the log output; note that it shows role environment is changing but then it stops the role even though I’ve confirmed in the debugger I’m returning e.cancel = false.
Any ideas?
===================
[fabric] Role state Started
[runtime] Role environment is changing
[fabric] Role state Stopping
[fabric] Role state Stopped
[fabric] Role state Teardown
[fabric] Role state Destroyed
[fabric] Role state Created
[fabric] Role state Suspended
[fabric] Role state Busy
[fabric] Role state Started
5:11 pm - March 11th, 2010
Hi Mike,
Yes it looks like this is actually an issue with the DevFabric. Check the link at the bottom to Jim Nakashima’s post on changing config in the dev fabric – it states near the bottom the following:
“not terribly useful in the July CTP as the role instances restart when the service configuration file changes”
Hopefully they will fix this up in a later release of the tools. But please test it actually works in the Azure fabric, I’m pretty sure it will.
Steve
2:56 am - March 13th, 2010
Yes, it works in cloud fabric. Thanks for the post – this approach is super useful. I’m writing an MSDN article on diagnostics in Azure for the June magazine and used your approach to move the verbosity switches to ServiceConfiguration.cscfg from app.config/web.config so I can change them at run-time without recycling the role.
One minor tweak – there is RoleEnvironmentChanging which gets called first before the change is in effect and then RoleEnvironmentChanged which is called afterwards. So your code above where you query the value in RoleEnvironmentChanging won’t actually work – it will get the OLD value. You have to have the code in RoleEnvironmentChanging to suppress the role recycle, then have similar code in RoleEnvironmentChanged (which you also have to register) to read the new value and apply it.
Do you mind if I give you a shout-out for this help at the end of my MSDN article?
8:18 pm - March 14th, 2010
Hi Mike,
No of course not. I’ve also added this article as a code project article too, might be better to link to that version: http://www.codeproject.com/KB/cs/azure-configuration.aspx
In relation to the events, thanks for that pickup. I’ll fix up my posts ASAP. And using it for debugging information level is a great example of the kind of configuration you would want to move into service configuration file.
Steve
1:02 am - July 24th, 2010
[...] and obviated the need for the SetConfigurationSettingPublisher in the OnStart method. Recommendation: For a deeper dive into the mechanics of SetConfigurationSettingPublisher check out Neil Mackensie’s blog as well as Steven Nagy’s. [...]
1:55 pm - November 22nd, 2010
[...] Windows Azure Deep Dive: Working with Configuration [...]
6:12 am - December 2nd, 2010
[...] Nagy has a good post on Azure configuration demonstrating the use of the Changing and Changed events. In the comments to [...]
1:45 am - February 18th, 2013
here…
Above The Cloud » Blog Archive » Windows Azure Development Deep Dive: Working With Configuration…
10:57 am - April 26th, 2013
Full Piece of writing…
Above The Cloud » Blog Archive » Windows Azure Development Deep Dive: Working With Configuration…