云计算设计模式(十九)——执行重构模式
设计应用程序,使得它能够在不须要又一次部署或者又一次启动应用程序又一次配置。这有助于保持可用性并降低停机时间。
背景和问题
一个主要目的为重要的应用。如商业和企业站点是尽量降低停机时间以及由此引发的中断给客户和用户。
可是。有时有必要又一次配置应用程序改变特定行为或设置,而在部署和使用。因此,它是用于该应用程序被设计成这样一种方式,以同意在执行时要应用这些配置的变化,并为应用程序。以检測所述变化而且尽快地应用它们的部件的长处。
该种要应用可能被调整记录,以协助与应用程序调试问题,交换使用不同数据存储的连接字符串。或者打开或关闭特定的部分或应用程序的功能的粒度配置变化的样例。
解决方式
为实施这一模式的解决方式依赖于应用程序托管环境中可用的功能。典型地,应用程序代码将响应于由检測到的变化相应用程序配置时,主机基础设施提出的一个或多个事件。这一般是上载新的配置文件,或响应于改变通过管理门户的配置或者通过訪问的API的结果。
码处理的配置变化事件能够检查变化。并将其应用到该应用程序的组件。有必要对这些部件进行检測和反应的变化,因此它们的值一般会被公开为可写的属性或方法,在事件处理程序的代码能够设置为新值,或运行。从这一点来说,该部件应使用新的值,以便在须要改变应用程序的行为发生。
假设这是不可能的部件。以应用更改在执行时。这将是必要的。又一次启动该应用程序。从而当应用程序启动时再次这些更改应用。在一些托管环境中它可能会检測到这些类型的变化。并指出对环境的应用程序必须又一次启动。在其它情况下。可能有必要执行该分析的设置更改。并强制必要的应用程序又一次启动时的代码。
图1示出了本模式的概述。
图1 - 此模式的基本概述
大多数环境中暴露响应配置更改引发的事件。在那些不这样做。定期检查更改配置并应用这些变化将是必要的轮询机制。
它也可能有必要又一次启动应用程序,假设变化不能在执行时被应用。
比如,有可能以比較在预设的时间间隔一个配置文件的日期和时间。并执行代码以应用更改时的较新版本号中找到。还有一种方法是,当中包括一个控制中的应用程序的管理用户界面,或使一个安全端点能够从应用程序外部进行訪问。其执行读取,并应用更新的配置的代码。
或者。该应用程序能够反应以在环境中的一些其它变化。比如,发生于特定的执行时错误可能会改变日志配置自己主动收集很多其它的信息,或者代码能够使用当前日期读取和应用主题,反映了季节或特殊事件。
问题和注意事项
在决定怎样实现这个模式时,请考虑下面几点:
?配置设置必须存储在部署的应用程序之外。使得它们能够在不须要整个包被又一次部署更新。典型的设置被存储在配置文件里。或者在外部存储库中。如一个数据库或网络存储。訪问执行时配置机制。应严格控制。以及使用时的严格审核。
?假设托管的基础设施不会自己主动检測配置更改的事件。揭露这些事件相应用程序代码,您必须实现一种替代机制来检測和应用更改。
这能够是通过轮询机制。或者通过暴露交互式控制或端点发起更新过程。
?假设您须要实现一个轮询机制。考虑怎样常常检查更新的配置应该发生。长轮询间隔将意味着变化可能不被应用了一段时间。短的间隔可能会产生不利影响,通过吸收现有的计算和I
/ O资源的操作。
?假设是应用程序的多个实例。附加的考虑因素,这取决于怎样变化进行检測。假设改变是通过由宿主基础结构引发的事件自己主动检測到,这些变化可能不被同一时候应用的全部实例进行检測。这意味着。某些情况下,将要使用的原始配置为一个周期。而有些则使用新的设置。
假设该更新是通过轮询机制检測到,这必须以保持一致性通信改变到全部实例。
?一些配置的变化可能要求应用程序又一次启动,甚至要求托管server又一次启动。您必须确定这些类型的配置设置和运行的每个对应的操作。
比如,要求应用程序又一次启动的变化可能会自己主动运行此操作,或者它可能是管理员负责发起又一次启动在适当的时间时。应用过大的负荷和应用程序能够处理的其它实例下是不的负载。
?更新并确认他们是成功的,而更新的应用程序实例正在运行正确。将更新应用到全部实例之前的分阶段部署计划。
由此,可以防止应错误发生的应用程序的总的中断。凡更新须要又一次启动或应用程序的又一次启动。特别是在应用程序有一个显著启动或热身的时候,用一个分阶段部署的方式,以防止多个实例脱机在同一时间。
?考虑怎样将回滚造成的问题配置更改。或导致申请失败。比如,它应该可以滚动的等待轮询间隔,以检測所述变化背部的变化马上取代。
?考虑怎样配置设置的位置可能会影响应用程序的性能。比如,你应该处理将发生,假设您使用外部存储不可用的错误。当应用程序启动时,或配置更改将被应用,比方用一个默认的配置或通过本地缓存的设置在server和重用这些值而重试訪问远程数据存储。
?快速缓存能够帮助降低延迟,假设一个组件须要多次訪问配置设置。
然而。当配置改变时。应用程序代码将须要无效缓存设置。该组件必须使用更新后的设置。
何时使用这个模式
这样的模式很适合于:
?应用程序,而您必须避免一切不必要的停机时间。同一时候仍然可以将更改应用到应用程序配置。
?环境,揭露事件自己主动提出的主要配置更改时。通常。这是当检測到一个新的配置文件,或者更改了现有的配置文件。
?应用的地方,往往配置更改和变化能够应用于组件。而不要求应用程序又一次启动。或无需托管server必须又一次启动。
这样的模式可能不是合适的,假设执行时组件的设计使得它们仅仅能在初始化时被配置,并更新这些部件的努力不能相比。又一次启动应用程序和持久的一个短的停机时间是合理的。
样例
微软Azure云服务的角色发现和揭露被提了两个事件,当主机环境检測变化的ServiceConfiguration.cscfg文件:
?RoleEnvironment.Changing。引发此事件被检測到的结构变化后,但在此之前它被施加到该应用程序。你能够处理查询的变化,并取消执行时又一次配置的活动。假设取消了变化,网页或辅助角色将自己主动以使新配置被应用程序使用的又一次启动。
?RoleEnvironment.Changed。引发此事件后,应用程序的配置得到了应用。能够处理该事件来查询所应用的改变。
当取消在RoleEnvironment.Changing事件改变要表示到Azure,一个新的设置不能被应用于该应用程序正在执行时,而且它必须以使用新的值被又一次启动。有效地,你会取消更改仅仅有在您的应用程序或组件无法反应在执行时改变,须要又一次启动才干使用新的值。
注意:
欲了解很多其它信息。请參阅RoleEnvironment.Changing事件并使用RoleEnvironment.Changing事件MSDN上。
处理RoleEnvironment.Changing和RoleEnvironment.Changed事件,你一般会加入一个自己定义处理该事件。比如,从你能够下载本手冊的样例执行时又一次配置的解决方式的Global.asax.cs类以下的代码显示了怎样加入一个名为RoleEnvironment_Changed到事件处理链中的自己定义函数。
这是从实施例的的Global.asax.cs文件。
注意:
这样的模式的样例是,在RuntimeReconfiguration解决方式的RuntimeReconfiguration.Web项目。
protected void Application_Start(object sender, EventArgs e) { ConfigureFromSetting(CustomSettingName); RoleEnvironment.Changed += this.RoleEnvironment_Changed; }
在Web或工作的角色,你能够在处理RoleEnvironment.Changing事件的作用的OnStart事件处理程序中使用类似的代码。这是从实施例的WebRole.cs文件。
public override bool OnStart() { // Add the trace listener. The web role process is not configured by web.config. Trace.Listeners.Add(new DiagnosticMonitorTraceListener()); RoleEnvironment.Changing += this.RoleEnvironment_Changing; return base.OnStart(); }
要注意的是。在网页的角色的情况下,所述的OnStart事件处理程序中从Web应用程序本身的单独进程中执行。这就是为什么你一般会处理在Global.asax文件里RoleEnvironment.Changed事件处理程序。让您能够更新您的Web应用程序的执行时配置,而RoleEnvironment.Changing事件中的角色本身。在辅助角色的情况下。您能够订阅两方RoleEnvironment.Changing和RoleEnvironment.Changed的的OnStart事件处理程序中的事件。
注意:
能够在服务配置文件中存储自己定义的配置设置,在自己定义配置文件,在数据库中,如在虚拟机中的Azure
SQL数据库或SQL Server,或者在天青blob和表存储。
您须要创建一个能够訪问自己定义配置设置和应用程序内设置组件的属性,这些适用于应用程序通常代码。
比如,以下的自己定义函数读取设置,其名称作为參数传递。从Azure的服务配置文件里的值。然后将它应用到一个名为SomeRuntimeComponent执行时组件的当前实例。这是从实施例的的Global.asax.cs文件
private static void ConfigureFromSetting(string settingName) { var value = RoleEnvironment.GetConfigurationSettingValue(settingName); SomeRuntimeComponent.Instance.CurrentValue = value; }
注意:
一些配置设置,如那些用于Windows标识框架,不能存储在Azure服务配置文件里。而且必须在App.config或Web.config文件。
在Azure中,一些配置的变化检測,并自己主动应用。
这包含在Diagnostics.wadcfg文件寡妇天青诊断系统,它指定的信息类型来收集和怎样保持日志文件的结构。因此,它仅须要编写处理加入到服务配置文件的自己定义设置的代码。你的代码应该:
?从更新的配置应用自己定义设置您的应用程序在执行时的对应组件,使他们的行为体现了新的配置。
?取消改变,以指示到Azure新的值不能在执行时应用,该应用程序必须按顺序又一次開始对要应用的变化。
比如,从你可以下载本手冊的样例执行时又一次配置的解决方式WebRole.cs类以下的代码显示了怎样使用RoleEnvironment.Changing事件取消全部设置的更新,除了可应用于那些在执行时。不须要又一次启动。
此演示样例同意在执行时应用无需又一次启动应用程序(使用此设置将可以读取新的值。并对应地在执行时改变其行为的组成部分)更改为“CustomSetting”的设置。不论什么其它更改的配置将自己主动使网页或工作的角色又一次启动。
private void RoleEnvironment_Changing(object sender, RoleEnvironmentChangingEventArgs e) { var changedSettings = e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>() .Select(c => c.ConfigurationSettingName).ToList(); Trace.TraceInformation("Changing notification. Settings being changed: " + string.Join(", ", changedSettings)); if (changedSettings .Any(settingName => !string.Equals(settingName, CustomSettingName, StringComparison.Ordinal))) { Trace.TraceInformation("Cancelling dynamic configuration change (restarting)."); // Setting this to true will restart the role gracefully. If Cancel is not // set to true, and the change is not handled by the application, the // application will not use the new value until it is restarted (either // manually or for some other reason). e.Cancel = true; } Else { Trace.TraceInformation("Handling configuration change without restarting. "); } }
注意:
这样的方法证明了好的做法,由于它确保了更改应用程序代码不知道不论什么设置(因此不能确保它能够在执行时应用)将导致又一次启动。假设更改不论什么一个被取消,该角色将被又一次启动。
然后能够检測到并应用于应用程序的组件的新的配置后已被接受由Azure的框架更新未在RoleEnvironment.Changing事件处理程序取消。比如,在该演示样例解决方式的Global.asax文件下面代码处理RoleEnvironment.Changed事件。它检查每一个配置设置,而且当它找到名为“CustomSetting”的设置,调用一个函数(前面所看到的),该应用新的设置。以在应用程序中的适当组件。
private void RoleEnvironment_Changed(object sender, RoleEnvironmentChangedEventArgs e) { Trace.TraceInformation("Updating instance with new configuration settings."); foreach (var settingChange in e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()) { if (string.Equals(settingChange.ConfigurationSettingName, CustomSettingName, StringComparison.Ordinal)) { // Execute a function to update the configuration of the component. ConfigureFromSetting(CustomSettingName ); } } }
须要注意的是,假设你不取消配置的变化。但不将新值应用到您的应用程序组件,那么更改将不会生效的下一次又一次启动应用程序之前。这可能会导致不可预測的行为,尤其是当所述宿主角色实例由Azure的自己主动重新启动在其日常维护操作。在该点的新的设定值将被应用的一部分。
本文翻译自MSDN:http://msdn.microsoft.com/en-us/library/dn589785.aspx