Handling Configuration Changes in Windows Azure Applications
- by Your DisplayName here!
While finalizing StarterSTS 1.5, I had a closer look at lifetime and configuration
management in Windows Azure.
(this is no new information – just some bits and pieces compiled at one single place
– plus a bit of reality check)
When dealing with lifetime management (and especially configuration changes), there
are two mechanisms in Windows Azure – a RoleEntryPoint derived class and
a couple of events on the RoleEnvironment class. You can find good documentation
about RoleEntryPoint here.
The RoleEnvironment class features two events that deal with configuration
changes – Changing and Changed.
Whenever a configuration change gets pushed out by the fabric controller (either changes
in the settings section or the instance count of a role) the Changing event
gets fired. The event handler receives an instance of the RoleEnvironmentChangingEventArgs type.
This contains a collection of type RoleEnvironmentChange. This in turn is
a base class for two other classes that detail the two types of possible configuration
changes I mentioned above: RoleEnvironmentConfigurationSettingsChange (configuration
settings) and RoleEnvironmentTopologyChange (instance count). The two respective
classes contain information about which configuration setting and which role has been
changed. Furthermore the Changing event can trigger a role recycle (aka reboot)
by setting EventArgs.Cancel to true.
So your typical job in the Changing event handler is to figure if your application
can handle these configuration changes at runtime, or if you rather want a clean restart.
Prior to the SDK 1.3 VS Templates – the following code was generated to reboot if
any configuration settings have changed:
private void RoleEnvironmentChanging(object sender,
RoleEnvironmentChangingEventArgs e)
{
// If a configuration setting
is changing
if (e.Changes.Any(change
=> change is RoleEnvironmentConfigurationSettingChange))
{
// Set
e.Cancel to true to restart this role instance
e.Cancel = true;
}
}
This is a little drastic as a default since most applications will work just fine
with changed configuration – maybe that’s the reason this code has gone away in the
1.3 SDK templates (more).
The Changed event gets fired after the configuration changes have been applied.
Again the changes will get passed in just like in the Changing event. But
from this point on RoleEnvironment.GetConfigurationSettingValue() will return
the new values. You can still decide to recycle if some change was so drastic that
you need a restart. You can use RoleEnvironment.RequestRecycle() for that
(more).
As a rule of thumb: When you always use GetConfigurationSettingValue to read
from configuration (and there is no bigger state involved) – you typically don’t need
to recycle.
In the case of StarterSTS, I had to abstract away the physical configuration system
and read the actual configuration (either from web.config or the Azure service configuration)
at startup. I then cache the configuration settings in memory. This means I indeed
need to take action when configuration changes – so in my case I simply clear the
cache, and the new config values get read on the next access to my internal configuration
object. No downtime – nice!
Gotcha
A very natural place to hook up the RoleEnvironment lifetime events is the RoleEntryPoint derived
class. But with the move to the full IIS model in 1.3 – the RoleEntryPoint methods
get executed in a different AppDomain (even in a different process) – see here..
You might no be able to call into your application code to e.g. clear a cache. Keep
that in mind! In this case you need to handle these events from e.g. global.asax.