您的位置:首页 > 大数据 > 云计算

Cloud Design Pattern - External Configuration Store(配置外部集中)

2015-11-08 10:21 591 查看
1.前言

每个系统都会有一些配置信息,比如数据库的连接字符串,日志文件路径等等.在云计算的环境中,系统被划分成独立的模块单独运行,如果每一个模块都有自己独立的配置,那么一旦某个配置需要变更,那必须手动修改配置文件,这样做是十分繁琐的,尤其是公共的配置,整个服务需要重启,对业务会造成不良的影响.

2.概念

配置外置即建立一个配置中心,所有的模块从这里读取配置信息,一旦配置变更,只需要在配置中心做修改就可以了,无需对每一个模块逐一进行修改.



这种模式需要在多个应用开发时就做好规划,否则无法把握哪些配置需要集中存放.对于云端应用来说,把配置存放在云存储中是非常合适的一种做法.比如在Windows Azure Cloud 中,我们使用Azure Storage来存储配置,这也是非常符合Azure的理念要求的.

3.示例

下面的示例介绍了Windows Azure中如何实现这种模式.

首先我们需要定义一个ISettingSote接口,然后实现这个接口.

public interface IsettingsStore
{
string Version { get; }

Dictionary<string, string> FindAll();

void Update(string key, string value);
}
接口定义了配置的版本,使用Key/Value的形式来记录配置信息和一个更新配置的方法.

class BlobSettingsStore:ISettingStore
{
string Version{get;}

Dictionary<string, string> FindAll()
{
}

void Update(string key,string value)
{
}
}
接下来,我们需要定义一个SettingStore的Manager类来实现对存储信息的管理.这里我们会使用到缓存,使用缓存能够提高性能,具体机制与Cache Aside 模式一模一样.

public class ExternalConfigurationManager : IDisposable
{
// An abstraction of the configuration store.
private readonly ISettingsStore settings;
private readonly ISubject<KeyValuePair<string, string>> changed;
...
private Dictionary<string, string> settingsCache;
private string currentVersion;
...
public ExternalConfigurationManager(ISettingsStore settings, ...)
{
this.settings = settings;
...
}
...
public IObservable<KeyValuePair<string, string>> Changed
{
get { return this.changed.AsObservable(); }
}
...
public void SetAppSetting(string key, string value)
{
...
// Update the setting in the store.
this.settings.Update(key, value);

// Publish the event.
this.Changed.OnNext(
new KeyValuePair<string, string>(key, value));

// Refresh the settings cache.
this.CheckForConfigurationChanges();
}

public string GetAppSetting(string key)
{
...
// Try to get the value from the settings cache.
// If there is a miss, get the setting from the settings store.
string value;
if (this.settingsCache.TryGetValue(key, out value))
{
return value;
}

// Check for changes and refresh the cache.
this.CheckForConfigurationChanges();

return this.settingsCache[key];
}
...
private void CheckForConfigurationChanges()
{
try
{

// Assume that updates are infrequent. Lock to avoid
// race conditions when refreshing the cache.
lock (this.settingsSyncObject)
{          {
var latestVersion = this.settings.Version;

// If the versions differ, the configuration has changed.
if (this.currentVersion != latestVersion)
{
// Get the latest settings from the settings store and publish the changes.
var latestSettings = this.settings.FindAll();
latestSettings.Except(this.settingsCache).ToList().ForEach(
kv => this.changed.OnNext(kv));

// Update the current version.
this.currentVersion = latestVersion;

// Refresh settings cache.
this.settingsCache = latestSettings;
}
}
}
catch (Exception ex)
{
this.changed.OnError(ex);
}
}
}
在ExternalConfigurationManager中可以增加一个Environment字段来实现在不同的环境中共享配置,比如生产环境(Production)和过度环境(Staging)环境.在Cache Aside模式中,我们实现了定时去更新缓存,我们这里也可以实现这种机制,定时去检查配置是否有更新.(使用Timer机制),下面的代码展示了这种机制.

public class ExternalConfigurationManager : IDisposable
{
...
private readonly ISubject<KeyValuePair<string, string>> changed;
private readonly Timer timer;
private ISettingsStore settings;
...
public ExternalConfigurationManager(ISettingsStore settings,
TimeSpan interval, ...)
{
...

// Set up the timer.
this.timer = new Timer(interval.TotalMilliseconds)
{
AutoReset = false;
};
this.timer.Elapsed += this.OnTimerElapsed;

this.changed = new Subject<KeyValuePair<string, string>>();
...
}

...

public void StartMonitor()
{
if (this.timer.Enabled)
{
return;
}

lock (this.timerSyncObject)
{
if (this.timer.Enabled)
{
return;
}
this.keepMonitoring = true;

// Load the local settings cache.
this.CheckForConfigurationChanges();

this.timer.Start();
}
}

public void StopMonitor()
{
lock (this.timerSyncObject)
{
this.keepMonitoring = false;
this.timer.Stop();
}
}

private void OnTimerElapsed(object sender, EventArgs e)
{
Trace.TraceInformation(
"Configuration Manager: checking for configuration changes.");

try
{
this.CheckForConfigurationChanges();
}
finally
{
...
// Restart the timer after each interval.
this.timer.Start();
...
}
}
...
}
这个ExternalConfigurationManager类在初始化的时候,通过单例模式来实现初始化.示例代码如下:

public static class ExternalConfiguration
{
private static readonly Lazy<ExternalConfigurationManager> configuredInstance
= new Lazy<ExternalConfigurationManager>(
() =>
{
var environment = CloudConfigurationManager.GetSetting("environment");
return new ExternalConfigurationManager(environment);
});

public static ExternalConfigurationManager Instance
{
get { return configuredInstance.Value; }
}
}
在Windows Azure Work Role中,在Run方法中启用配置.

public override void Run()
{
// Start monitoring for configuration changes.
ExternalConfiguration.Instance.StartMonitor();

// Get a setting.
var setting = ExternalConfiguration.Instance.GetAppSetting("setting1");
Trace.TraceInformation("Worker Role: Get setting1, value: " + setting);

Thread.Sleep(TimeSpan.FromSeconds(10));

// Update a setting.
Trace.TraceInformation("Worker Role: Updating configuration");
ExternalConfiguration.Instance.SetAppSetting("setting1", "new value");

this.completeEvent.WaitOne();
}
下面的代码展示了再Azure Work Role中如何更新配置.

public override void Run()
{
// Start monitoring for configuration changes.
ExternalConfiguration.Instance.StartMonitor();

// Get a setting.
var setting = ExternalConfiguration.Instance.GetAppSetting("setting1");
Trace.TraceInformation("Worker Role: Get setting1, value: " + setting);

Thread.Sleep(TimeSpan.FromSeconds(10));

// Update a setting.
Trace.TraceInformation("Worker Role: Updating configuration");
ExternalConfiguration.Instance.SetAppSetting("setting1", "new value");

this.completeEvent.WaitOne();
}
4.相关阅读

The following pattern may also be relevant when implementing this pattern:

Runtime Reconfiguration Pattern. In addition to storing configuration externally, it is useful
to be able to update configuration settings and have the changes applied without restarting the application. The Runtime Reconfiguration pattern describes how to design an application so that it can be reconfigured without requiring redeployment or restarting.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息