云计算设计模式(八)——外部配置存储模式

云计算设计模式(八)——外部配置存储模式

移动配置信息从应用部署包到一个集中位置。这个模式可以提供机会,以便管理和配置数据的控制,以及用于跨应用程序和应用程序实例共享的配置数据。

背景和问题

大多数应用程序运行时环境包括位于应用程序文件夹内的在部署应用程序文件保持配置信息。在某些情况下也能够编辑这些文件来改变该应用程序的行为,它已经被部署之后。然而,在许多情况下,改变配置所需要的应用程序被重新部署,从而导致不可接受的停机时间和额外的管理开销。

本地配置文件还配置限制为单个应用程序,而在某些情况下将是有用的,以在多个应用程序之间共享的配置设置。例子包括数据库连接字符串,UI主题的信息,或队列和存储所使用的一组相关的应用程序的URL。

变更管理跨应用程序的多个运行实例的本地配置,尤其是在云托管的情况,也可能是具有挑战性的。它可能会导致使用不同的配置设置的实例,而更新正被部署。

另外,更新应用程序和组件可能需要更改的配置方案。许多配置系统不支持不同版本的配置信息。

解决方案

存储在外部存储器中的配置信息,并提供可用于快速和有效地读取和更新的配置设置的接口。外部存储的类型取决于应用程序的主机和运行时环境。在一个云托管的情况下它是一个典型的基于云的存储服务,但可能是一个托管数据库或其他系统。

选择用于配置信息的备份存储应通过适当的接口,它提供了一个可控制的方式,使回用保持一致和易于使用的访问被朝向。理想情况下,它应该公开在键入正确,结构化的格式的信息。的实施也可能需要对用户进行授权“,以保护结构的数据访问,并且具有足够的灵活性,以允许要被存储的多个版本的配置(例如,开发,分段,或生产,并且每一个的多个发行版本)。

注意:

许多内置的系统配置中读取数据时,应用程序启动和高速缓存内存中的数据提供快速访问,并尽量减少对应用程序性能的影响。根据所使用的后备存储器的类型,以及该商店的等待时间,这可能是有利的,以实现外部配置存储器内的高速缓存机制。有关实现缓存的详细信息,请参阅缓存指导。

图1示出了本模式的概述。

 

图1  - 外部配置存储模式可选本地缓存概述

问题和注意事项

在决定如何实现这个模式时,请考虑以下几点:

•选择一个后备存储,提供可接受的性能,高可用性,健壮性和可备份作为应用程序的维护和管理过程的一部分。在一个云托管的应用程序,使用云存储的机制通常是一个不错的选择,以满足这些要求。

•设计的后备存储的架构允许在信息能够保存类型的灵活性。确保它提供了一种使用它可以要求该申请的所有配置的要求,例如输入数据中,设置的集合,多个版本的设置,以及任何其他功能。该模式应该是易于扩展的需求,以支持更多的设置更改。

•考虑后备存储的物理性能,它与配置信息的存储方式,以及对性能的影响。例如,存储一个包含XML文件的配置信息将要求使用配置界面或应用程序解析该文件以读取各个设置,将使得更新的设置更加复杂,尽管高速缓存中的设置可有助于抵消较慢的读取性能。

•考虑如何配置界面将允许配置设置的范围和继承的控制权。例如,它可能是一个要求的范围的配置设置在组织,应用程序和设备的水平;支持在访问不同范围的控制下放;并且,以防止或允许单独的应用程序,以覆盖设置。

•确保配置界面可以在需要的格式的配置数据暴露,如输入值的集合,键/值对,或财产包。然而,考虑能力和API的复杂性之间的平衡,以使其有用的,但尽可能地易于使用。

•考虑配置存储界面将如何表现时,设定有误,或没有在内部存储存在。它可能是适当的,返回默认设置和记录错误。也可以考虑,如配置设置按键或者名称,二进制数据的存储和处理,以及null或空值处理方式的情况下,灵敏度方面。

•考虑如何将保护配置数据仅允许访问相应的用户和应用程序。这很可能是在配置存储器接口的一个特征,但它也是必要的,以确保在后备存储器中的数据不能被直接访问,而不适当的权限。确保读取和写入配置数据所需的权限之间的严格分离。也可以考虑是否需要加密部分的配置设置或全部,以及如何将配置存储接口中实现。

•请记住,集中存储配置,这在运行时改变应用程序的行为,是非常重要的,并应部署,更新,并使用相同的机制,部署应用程序代码进行管理。例如,可能会影响多个应用程序的更改,必须进行使用一个完整的测试和分阶段部署的方式,以确保变化是适用于所有使用该配置的应用程序。如果管理员简单地进行编辑的设置来更新一个应用程序,它可以产生不利使用相同设置的其他应用程序的影响。

•如果应用程序的高速缓存的配置信息,应用程序可能需要的,如果配置更改被提醒。有可能实现的过期策略在缓存中的配置数据,使这些信息被自动定期刷新任何更改拿起(和付诸行动)。本指南中其他地方所描述的运行模式重构可能有关您的方案。

何时使用这个模式

这种模式非常适合于:
•被多个应用程序和应用程序实例,或在标准配置中,必须跨多个应用程序和应用程序实例执行之间共享配置设置。

•在标准配置的系统不支持所有所需的配置设置,如存储图像或复杂的数据类型。

•作为补充商店的一些应用程序的设置,或许允许应用程序重写一些集中存储或所有设置。

•作为一种机制,通过记录的部分或全部类型的访问来配置存储监控使用的配置设置简化了多个应用程序管理,以及可选。

例子

在微软Azure托管应用,用于从外部存储配置信息的典型的选择是使用Azure存储。这是有弹性的,提供高性能,并重复3次自动故障切换提供高可用性。
Azure的表格提供了一个键/值存储与使用一个灵活的架构的价值的能力。
Azure的Blob存储提供了一个分层的基于容器的存储,可以保存任何类型的单独命名的blob数据。

下面的示例显示了如何配置存储可以通过Azure的Blob存储来实现存储和揭露的配置信息。该BlobSettingsStore类文摘Blob存储用于保存配置信息,并实现在下面的代码所示ISettingsStore接口。

注意:

此代码在ExternalConfigurationStore解决方案ExternalConfigurationStore.Cloud项目提供。该解决方案可用于下载本指导意见。

public interface IsettingsStore
{
  string Version { get; }

  Dictionary<string, string> FindAll();

  void Update(string key, string value);
} 

 

该接口定义的方法,用于检索和更新在配置存储中保持的配置设置,并且包括可用于检测是否有任何配置设置最近已修改的版本号。何时配置设置被更新时,版本号的变化。该BlobSettingsStore类使用BLOB的ETag的属性来实现的版本。一个blob的ETag的属性将BLOB写入每一次自动更新。

注意:

需要注意的是,按照设计,这个简单的解决方案,展现了所有的配置设置为字符串值,而不是类型的值。

该ExternalConfigurationManager类提供了围绕BlobSettingsStore物体的包装。应用程序可以使用这个类来存储和检索配置信息。这个类使用Microsoft无扩展库来揭露过的IObservable接口的实现做出任何配置更改。如果设置是通过调用SetAppSetting法修改,更改的事件引发,所有订阅者此事件将被通报。

请注意,所有的设置也缓存到ExternalConfigurationManager类快速访问内部Dictionary对象。该SetAppSetting方法更新该高速缓存中,并且该应用程序可以使用以检索配置设置的GetSetting方法从高速缓存中读取数据(如果未在该高速缓存中找到该设置,它从BlobSettingsStore对象检索代替)。

所述的getSettings方法调用CheckForConfigurationChanges的方法来检测在Blob存储的配置信息是否通过检查版本号,并将它与所述ExternalConfigurationManager对象保持当前的版本号进行比较已经改变。如果一个或多个已经发生了变化,改变的事件引发,并缓存在Dictionary对象的配置设置被刷新。这是缓存除了图案的应用。

下面的代码示例演示如何更改的情况下,SetAppSettings方法,该方法的getSettings和CheckForConfigurationChanges方法实现

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属性。此属性的目的是为了支持不同的配置为在不同的环境中,如临时和生产运行的应用程序。

一个ExternalConfigurationManager对象也可以定期查询BlobSettingsStore对象的任何变化(通过使用定时器)。该StartMonitor和StopMonitor方法如下图所示的启动代码示例和停止计时器。该OnTimerElapsed方法当定时器到期时,并调用CheckForConfigurationChanges方法来检测的任何变化,并提高了变更的情况下,如前面所描述运行。

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类被实例化作为由ExternalConfiguration类如下所示的单一实例。

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; }
  }
}

 

下面的代码取自WorkerRole类中ExternalConfigurationStore.Cloud项目。它显示了如何在应用程序使用ExternalConfiguration类读取和更新设置。

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();
}

下面的代码,也是从WorkerRole类,展示了如何应用订阅配置事件。

public override bool OnStart()
{
  ...
  // Subscribe to the event.
  ExternalConfiguration.Instance.Changed.Subscribe(
     m => Trace.TraceInformation("Configuration has changed. Key:{0} Value:{1}",
          m.Key, m.Value),
     ex => Trace.TraceError("Error detected: " + ex.Message));
  ...
}

本文翻译自MSDN:http://msdn.microsoft.com/en-us/library/dn589803.aspx

 

 

 

 

时间: 2024-07-28 18:18:44

云计算设计模式(八)——外部配置存储模式的相关文章

云计算设计模式(十)——守门员模式

云计算设计模式(十)--守门员模式 通过使用充当客户端和应用程序或服务之间的代理,验证和进行消毒的请求,并将它们之间的请求和数据的专用主机实例保护的应用程序和服务.这可以提供一个额外的安全层,并限制了系统的攻击面. 背景和问题 应用程序通过接受和处理请求揭露它们的功能提供给客户.在云托管方案,应用程序暴露终端客户机连接,一般包括代码来处理来自客户端的请求.此代码可以执行认证和验证,一些或所有请求的处理,并有可能访问存储等服务代表客户端的. 如果恶意用户能够危及系统和访问应用程序的托管环境,它使用

云计算设计模式(二)——断路器模式

云计算设计模式(二)--断路器模式 处理故障连接到远程服务或资源时,可能需要耗费大量的时间.这种模式可以提高应用程序的稳定性和灵活性. 背景和问题 在分布式环境中,如在云,其中,应用程序执行访问远程资源和服务的操作,有可能对这些操作的失败是由于瞬时故障,如慢的网络连接,超时,或者被过度使用的资源或暂时不可用.这些故障一般之后的短时间内纠正自己,和一个强大的云应用应该准备使用的策略来处理它们,例如,通过重试模式进行说明. 但是,也可以是其中的故障是由于那些不容易预见的突发事件的情况下,这可能需要更

云计算设计模式(十八)——重试模式

云计算设计模式(十八)--重试模式 启用应用程序来处理预期的,暂时的失败时,它会尝试连接到由透明的重试操作了以前失败的期望,失败的原因是瞬时的服务或网络资源.这种模式可以提高应用程序的稳定性. 背景和问题 该通信的应用程序与在云中运行的元素必须是可能发生在这样的环境中的瞬时故障敏感.这些故障包括网络连接的过程中出现时,一个服务是忙碌的瞬时损失的组件和服务中,服务的临时不可用,或超时. 这些故障一般是自校正的,如果经过一个合适的延迟被重复触发一个故障的动作很可能是成功的.例如,数据库服务,它正在处

云计算设计模式(十九)——运行重构模式

云计算设计模式(十九)--运行重构模式 设计应用程序,使得它可以在不需要重新部署或者重新启动应用程序重新配置.这有助于保持可用性并减少停机时间. 背景和问题 一个主要目的为重要的应用,如商业和企业网站是尽量减少停机时间以及由此引发的中断给客户和用户.但是,有时有必要重新配置应用程序改变特定行为或设置,而在部署和使用.因此,它是用于该应用程序被设计成这样一种方式,以允许在运行时要应用这些配置的变化,并为应用程序,以检测所述变化并且尽快地应用它们的部件的优点. 该种要应用可能被调整记录,以协助与应用

云计算设计模式(九)——联合身份模式

云计算设计模式(九)--联合身份模式 验证委托给外部身份提供者.这种模式可以简化开发,最大限度地减少对用户管理的要求,并提高了应用程序的用户体验. 背景和问题 用户通常需要使用由提供,并通过与它们有商业关系的不同组织主持的多个应用程序一起工作.但是,这些用户可能被迫使用特定的(和不同的)的凭证,每一个.这可以: •原因脱节的用户体验.用户经常忘记登录凭据时,他们有很多不同的的. •暴露安全漏洞.当用户离开公司的帐户,必须立即取消设置.这是很容易忽略这在大型组织中. •复杂的用户管理.管理员必须管

云计算设计模式(二十二)——静态内容托管模式

云计算设计模式(二十二)--静态内容托管模式 部署静态内容到一个基于云的存储服务,可以直接向客户提供这些.这个模式可以减少潜在的昂贵的计算实例的需求. 景和问题 Web应用程序通常包括静态内容的一些元素.此静态内容可以包括HTML页面和诸如图像和可用到客户端的文件的其他资源,无论是作为一个HTML页的一部分(如嵌入式图像,样式表和客户端JavaScript文件)或作为单独的下载(如PDF文档). 尽管Web服务器以及调整通过有效的动态执行页代码和输出缓存优化的要求,他们仍然必须处理请求下载静态内

云计算设计模式(十一)——健康端点监控模式

云计算设计模式(十一)--健康端点监控模式 实施外部工具可以定期通过暴露终端访问应用程序中的功能检查.这个模式可以帮助验证的应用和服务被正确执行 背景和问题 它是很好的做法,并且通常是一个业务需求,并监控web应用程序,和中间层和共享服务,以确保它们是可用的,并执行正确的.然而,它更难以监测在云中运行比它要监控本地服务的服务.举例来说,你不必完全控制主机环境,而服务通常依赖于平台,供应商和其他公司提供其他服务. 也有一些影响云托管的应用,如网络延迟,性能和下面的计算和存储系统的可用性,以及它们之

云计算设计模式(一)——缓存预留模式

云计算设计模式(一)--缓存预留模式 根据需求从数据存储缓存加载数据.这种模式可以提高性能,并有助于维持在基础数据存储在高速缓存中保持的数据和数据之间的一致性. 背景和问题 应用程序使用的高速缓存来优化重复访问的数据存储中保持的信息.然而,它通常是不切实际的期望缓存的数据将始终与在数据存储器中的数据完全一致.应用程序要实现一种策略,有助于确保在高速缓存中的数据是最新的,只要有可能,但也可以检测和处理的过程中出现,当在高速缓存中的数据已经变得陈旧的情况. 解决方案 许多商业缓存系统提供通读和直写式

云计算设计模式(二十四)——仆人键模式

云计算设计模式(二十四)--仆人键模式 使用一个令牌或密钥,向客户提供受限制的直接访问特定的资源或服务,以便由应用程序代码卸载数据传输操作.这个模式是在使用云托管的存储系统或队列的应用中特别有用,并且可以最大限度地降低成本,最大限度地提高可扩展性和性能. 背景和问题 客户端程序和网络浏览器经常需要读取和写入文件或数据流,并从一个应用程序的存储空间.通常,应用程序将处理的运动数据,或者通过从存储读取它,并将其传输到客户端,或通过从客户机读取该载流并将其存储在数据存储中.然而,这种方法吸收了宝贵的资