設(shè)計(jì)應(yīng)用程序,使得它可以在不需要重新部署或者重新啟動(dòng)應(yīng)用程序重新配置。這有助于保持可用性并減少停機(jī)時(shí)間。
一個(gè)主要目的為重要的應(yīng)用,如商業(yè)和企業(yè)網(wǎng)站是盡量減少停機(jī)時(shí)間以及由此引發(fā)的中斷給客戶和用戶。但是,有時(shí)有必要重新配置應(yīng)用程序改變特定行為或設(shè)置,而在部署和使用。因此,它是用于該應(yīng)用程序被設(shè)計(jì)成這樣一種方式,以允許在運(yùn)行時(shí)要應(yīng)用這些配置的變化,并為應(yīng)用程序,以檢測(cè)所述變化并且盡快地應(yīng)用它們的部件的優(yōu)點(diǎn)。
該種要應(yīng)用可能被調(diào)整記錄,以協(xié)助與應(yīng)用程序調(diào)試問題,交換使用不同數(shù)據(jù)存儲(chǔ)的連接字符串,或者打開或關(guān)閉特定的部分或應(yīng)用程序的功能的粒度配置變化的例子。
為實(shí)施這一模式的解決方案依賴于應(yīng)用程序托管環(huán)境中可用的功能。典型地,應(yīng)用程序代碼將響應(yīng)于由檢測(cè)到的變化對(duì)應(yīng)用程序配置時(shí),主機(jī)基礎(chǔ)設(shè)施提出的一個(gè)或多個(gè)事件。這通常是上載新的配置文件,或響應(yīng)于改變通過管理門戶的配置或者通過訪問的API的結(jié)果。
碼處理的配置變化事件可以檢查變化,并將其應(yīng)用到該應(yīng)用程序的組件。有必要對(duì)這些部件進(jìn)行檢測(cè)和反應(yīng)的變化,因此它們的值通常會(huì)被公開為可寫的屬性或方法,在事件處理程序的代碼可以設(shè)置為新值,或執(zhí)行。從這一點(diǎn)來說,該部件應(yīng)使用新的值,以便在需要改變應(yīng)用程序的行為發(fā)生。
如果這是不可能的部件,以應(yīng)用更改在運(yùn)行時(shí),這將是必要的,重新啟動(dòng)該應(yīng)用程序,從而當(dāng)應(yīng)用程序啟動(dòng)時(shí)再次這些更改應(yīng)用。在一些托管環(huán)境中它可能會(huì)檢測(cè)到這些類型的變化,并指出對(duì)環(huán)境的應(yīng)用程序必須重新啟動(dòng)。在其他情況下,可能有必要執(zhí)行該分析的設(shè)置更改,并強(qiáng)制必要的應(yīng)用程序重新啟動(dòng)時(shí)的代碼。
圖1示出了本模式的概述。
圖1 - 此模式的基本概述
大多數(shù)環(huán)境中暴露響應(yīng)配置更改引發(fā)的事件。在那些不這樣做,定期檢查更改配置并應(yīng)用這些變化將是必要的輪詢機(jī)制。它也可能有必要重新啟動(dòng)應(yīng)用程序,如果變化不能在運(yùn)行時(shí)被應(yīng)用。例如,有可能以比較在預(yù)設(shè)的時(shí)間間隔一個(gè)配置文件的日期和時(shí)間,并運(yùn)行代碼以應(yīng)用更改時(shí)的較新版本中找到。另一種方法是,其中包含一個(gè)控制中的應(yīng)用程序的管理用戶界面,或使一個(gè)安全端點(diǎn)可以從應(yīng)用程序外部進(jìn)行訪問,其執(zhí)行讀取,并應(yīng)用更新的配置的代碼。
或者,該應(yīng)用程序可以反應(yīng)以在環(huán)境中的一些其他變化。例如,發(fā)生于特定的運(yùn)行時(shí)錯(cuò)誤可能會(huì)改變?nèi)罩九渲米詣?dòng)收集更多的信息,或者代碼可以使用當(dāng)前日期讀取和應(yīng)用主題,反映了季節(jié)或特殊事件。
在決定如何實(shí)現(xiàn)這個(gè)模式時(shí),請(qǐng)考慮以下幾點(diǎn):
這種模式非常適合于:
這種模式可能不是合適的,如果運(yùn)行時(shí)組件的設(shè)計(jì)使得它們只能在初始化時(shí)被配置,并更新這些部件的努力不能相比,重新啟動(dòng)應(yīng)用程序和持久的一個(gè)短的停機(jī)時(shí)間是合理的。
微軟 Azure 云服務(wù)的角色發(fā)現(xiàn)和揭露被提了兩個(gè)事件,當(dāng)主機(jī)環(huán)境檢測(cè)變化的 ServiceConfiguration.cscfg 文件:
當(dāng)取消在 RoleEnvironment.Changing 事件改變要表示到 Azure,一個(gè)新的設(shè)置不能被應(yīng)用于該應(yīng)用程序正在運(yùn)行時(shí),并且它必須以使用新的值被重新啟動(dòng)。有效地,你會(huì)取消更改只有在您的應(yīng)用程序或組件無法反應(yīng)在運(yùn)行時(shí)改變,需要重新啟動(dòng)才能使用新的值。
注意: 欲了解更多信息,請(qǐng)參閱 RoleEnvironment.Changing 事件并使用 RoleEnvironment.Changing 事件 MSDN 上。
處理 RoleEnvironment.Changing 和 RoleEnvironment.Changed 事件,你通常會(huì)添加一個(gè)自定義處理該事件。例如,從你可以下載本手冊(cè)的例子運(yùn)行時(shí)重新配置的解決方案的 Global.asax.cs 類下面的代碼顯示了如何添加一個(gè)名為 RoleEnvironment_Changed 到事件處理鏈中的自定義函數(shù)。這是從實(shí)施例的的 Global.asax.cs 文件。
注意: 這種模式的例子是,在 RuntimeReconfiguration 解決方案的 RuntimeReconfiguration.Web 項(xiàng)目。
protected void Application_Start(object sender, EventArgs e)
{
ConfigureFromSetting(CustomSettingName);
RoleEnvironment.Changed += this.RoleEnvironment_Changed;
}
在 Web 或工作的角色,你可以在處理 RoleEnvironment.Changing 事件的作用的 OnStart 事件處理程序中使用類似的代碼。這是從實(shí)施例的 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();
}
要注意的是,在網(wǎng)頁(yè)的角色的情況下,所述的 OnStart 事件處理程序中從 Web 應(yīng)用程序本身的單獨(dú)進(jìn)程中運(yùn)行。這就是為什么你通常會(huì)處理在 Global.asax 文件中 RoleEnvironment.Changed 事件處理程序,讓您可以更新您的 Web 應(yīng)用程序的運(yùn)行時(shí)配置,而 RoleEnvironment.Changing 事件中的角色本身。在輔助角色的情況下,您可以訂閱雙方 RoleEnvironment.Changing和RoleEnvironment.Changed 的 OnStart 事件處理程序中的事件。
注意: 可以在服務(wù)配置文件中存儲(chǔ)自定義的配置設(shè)置,在自定義配置文件,在數(shù)據(jù)庫(kù)中,如在虛擬機(jī)中的 Azure SQ L數(shù)據(jù)庫(kù)或 SQL Server,或者在天青 blob 和表存儲(chǔ)。您需要?jiǎng)?chuàng)建一個(gè)可以訪問自定義配置設(shè)置和應(yīng)用程序內(nèi)設(shè)置組件的屬性,這些適用于應(yīng)用程序通常代碼。
例如,下面的自定義函數(shù)讀取設(shè)置,其名稱作為參數(shù)傳遞,從 Azure 的服務(wù)配置文件中的值,然后將它應(yīng)用到一個(gè)名為 SomeRuntimeComponent 運(yùn)行時(shí)組件的當(dāng)前實(shí)例。這是從實(shí)施例的的 Global.asax.cs 文件
private static void ConfigureFromSetting(string settingName)
{
var value = RoleEnvironment.GetConfigurationSettingValue(settingName);
SomeRuntimeComponent.Instance.CurrentValue = value;
}
注意
一些配置設(shè)置,如那些用于 Windows 標(biāo)識(shí)框架,不能存儲(chǔ)在 Azure 服務(wù)配置文件中,并且必須在 App.config 或 Web.config 文件。
在Azure中,一些配置的變化檢測(cè),并自動(dòng)應(yīng)用。這包括在 Diagnostics.wadcfg 文件寡婦天青診斷系統(tǒng),它指定的信息類型來收集和如何保持日志文件的結(jié)構(gòu)。因此,它僅需要編寫處理添加到服務(wù)配置文件的自定義設(shè)置的代碼。你的代碼應(yīng)該:
例如,從你可以下載本手冊(cè)的例子運(yùn)行時(shí)重新配置的解決方案 WebRole.cs 類下面的代碼顯示了如何使用 RoleEnvironment.Changing 事件取消所有設(shè)置的更新,除了可應(yīng)用于那些在運(yùn)行時(shí),不需要重新啟動(dòng)。此示例允許在運(yùn)行時(shí)應(yīng)用無需重新啟動(dòng)應(yīng)用程序(使用此設(shè)置將能夠讀取新的值,并相應(yīng)地在運(yùn)行時(shí)改變其行為的組成部分)更改為“CustomSetting”的設(shè)置。任何其他更改的配置將自動(dòng)使網(wǎng)頁(yè)或工作的角色重新啟動(dòng)。
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. ");
}
}
注意:這種方法證明了好的做法,因?yàn)樗_保了更改應(yīng)用程序代碼不知道任何設(shè)置(因此不能確保它可以在運(yùn)行時(shí)應(yīng)用)將導(dǎo)致重新啟動(dòng)。如果更改任何一個(gè)被取消,該角色將被重新啟動(dòng)。
然后可以檢測(cè)到并應(yīng)用于應(yīng)用程序的組件的新的配置后已被接受由 Azure 的框架更新未在 RoleEnvironment.Changing 事件處理程序取消。例如,在該示例解決方案的 Global.asax 文件以下代碼處理 RoleEnvironment.Changed 事件。它檢查每個(gè)配置設(shè)置,并且當(dāng)它找到名為“CustomSetting”的設(shè)置,調(diào)用一個(gè)函數(shù)(前面所示),該應(yīng)用新的設(shè)置,以在應(yīng)用程序中的適當(dāng)組件。
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 );
}
}
}
需要注意的是,如果你不取消配置的變化,但不將新值應(yīng)用到您的應(yīng)用程序組件,那么更改將不會(huì)生效的下一次重新啟動(dòng)應(yīng)用程序之前。這可能會(huì)導(dǎo)致不可預(yù)測(cè)的行為,尤其是當(dāng)所述宿主角色實(shí)例由 Azure 的自動(dòng)重啟在其日常維護(hù)操作,在該點(diǎn)的新的設(shè)定值將被應(yīng)用的一部分。
更多建議: