(十九)——運(yùn)行重構(gòu)模式

2018-02-24 15:44 更新

云計(jì)算設(shè)計(jì)模式(十九)——運(yùn)行重構(gòu)模式

設(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é)或特殊事件。

問題和注意事項(xiàng)

在決定如何實(shí)現(xiàn)這個(gè)模式時(shí),請(qǐng)考慮以下幾點(diǎn):

  • 配置設(shè)置必須存儲(chǔ)在部署的應(yīng)用程序之外,使得它們可以在不需要整個(gè)包被重新部署更新。典型的設(shè)置被存儲(chǔ)在配置文件中,或者在外部存儲(chǔ)庫(kù)中,如一個(gè)數(shù)據(jù)庫(kù)或網(wǎng)絡(luò)存儲(chǔ)。訪問運(yùn)行時(shí)配置機(jī)制,應(yīng)嚴(yán)格控制,以及使用時(shí)的嚴(yán)格審核。
  • 如果托管的基礎(chǔ)設(shè)施不會(huì)自動(dòng)檢測(cè)配置更改的事件,揭露這些事件對(duì)應(yīng)用程序代碼,您必須實(shí)現(xiàn)一種替代機(jī)制來檢測(cè)和應(yīng)用更改。這可以是通過輪詢機(jī)制,或者通過暴露交互式控制或端點(diǎn)發(fā)起更新過程。
  • 如果您需要實(shí)現(xiàn)一個(gè)輪詢機(jī)制,考慮如何經(jīng)常檢查更新的配置應(yīng)該發(fā)生。長(zhǎng)輪詢間隔將意味著變化可能不被應(yīng)用了一段時(shí)間。短的間隔可能會(huì)產(chǎn)生不利影響,通過吸收現(xiàn)有的計(jì)算和I / O資源的操作。
  • 如果是應(yīng)用程序的多個(gè)實(shí)例,附加的考慮因素,這取決于如何變化進(jìn)行檢測(cè)。如果改變是通過由宿主基礎(chǔ)結(jié)構(gòu)引發(fā)的事件自動(dòng)檢測(cè)到,這些變化可能不被同時(shí)應(yīng)用的所有實(shí)例進(jìn)行檢測(cè)。這意味著,某些情況下,將要使用的原始配置為一個(gè)周期,而有些則使用新的設(shè)置。如果該更新是通過輪詢機(jī)制檢測(cè)到,這必須以保持一致性通信改變到所有實(shí)例。
  • 一些配置的變化可能要求應(yīng)用程序重新啟動(dòng),甚至要求托管服務(wù)器重新啟動(dòng)。您必須確定這些類型的配置設(shè)置和執(zhí)行的每一個(gè)相應(yīng)的操作。例如,要求應(yīng)用程序重新啟動(dòng)的變化可能會(huì)自動(dòng)執(zhí)行此操作,或者它可能是管理員負(fù)責(zé)發(fā)起重新啟動(dòng)在適當(dāng)?shù)臅r(shí)間時(shí),應(yīng)用過大的負(fù)荷和應(yīng)用程序可以處理的其他實(shí)例下是不的負(fù)載。
  • 更新并確認(rèn)他們是成功的,而更新的應(yīng)用程序?qū)嵗趫?zhí)行正確,將更新應(yīng)用到所有實(shí)例之前的分階段部署計(jì)劃。由此,能夠防止應(yīng)發(fā)生錯(cuò)誤的應(yīng)用程序的總的中斷。凡更新需要重新啟動(dòng)或應(yīng)用程序的重新啟動(dòng),特別是在應(yīng)用程序有一個(gè)顯著啟動(dòng)或熱身的時(shí)候,用一個(gè)分階段部署的方式,以防止多個(gè)實(shí)例脫機(jī)在同一時(shí)間。
  • 考慮如何將回滾造成的問題配置更改,或?qū)е律暾?qǐng)失敗。例如,它應(yīng)該能夠滾動(dòng)的等待輪詢間隔,以檢測(cè)所述變化背部的變化立即代替。
  • 考慮如何配置設(shè)置的位置可能會(huì)影響應(yīng)用程序的性能。例如,你應(yīng)該處理將發(fā)生,如果您使用外部存儲(chǔ)不可用的錯(cuò)誤,當(dāng)應(yīng)用程序啟動(dòng)時(shí),或配置更改將被應(yīng)用,比如用一個(gè)默認(rèn)的配置或通過本地緩存的設(shè)置在服務(wù)器和重用這些值而重試訪問遠(yuǎn)程數(shù)據(jù)存儲(chǔ)。
  • 高速緩存可以幫助減少延遲,如果一個(gè)組件需要多次訪問配置設(shè)置。然而,當(dāng)配置改變時(shí),應(yīng)用程序代碼將需要無效緩存設(shè)置,該組件必須使用更新后的設(shè)置。

何時(shí)使用這個(gè)模式

這種模式非常適合于:

  • 應(yīng)用程序,而您必須避免一切不必要的停機(jī)時(shí)間,同時(shí)仍然能夠?qū)⒏膽?yīng)用到應(yīng)用程序配置。
  • 環(huán)境,揭露事件自動(dòng)提出的主要配置更改時(shí)。通常,這是當(dāng)檢測(cè)到一個(gè)新的配置文件,或者更改了現(xiàn)有的配置文件。
  • 應(yīng)用的地方,往往配置更改和變化可以應(yīng)用于組件,而不要求應(yīng)用程序重新啟動(dòng),或無需托管服務(wù)器必須重新啟動(dòng)。

這種模式可能不是合適的,如果運(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 文件:

  • RoleEnvironment.Changing。引發(fā)此事件被檢測(cè)到的結(jié)構(gòu)變化后,但在此之前它被施加到該應(yīng)用程序。你可以處理查詢的變化,并取消運(yùn)行時(shí)重新配置的活動(dòng)。如果取消了變化,網(wǎng)頁(yè)或輔助角色將自動(dòng)以使新配置被應(yīng)用程序使用的重新啟動(dòng)。
  • RoleEnvironment.Changed。引發(fā)此事件后,應(yīng)用程序的配置得到了應(yīng)用??梢蕴幚碓撌录聿樵兯鶓?yīng)用的改變。

當(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)該:

  • 從更新的配置應(yīng)用自定義設(shè)置您的應(yīng)用程序在運(yùn)行時(shí)的相應(yīng)組件,使他們的行為體現(xiàn)了新的配置。
  • 取消改變,以指示到 Azure 新的值不能在運(yùn)行時(shí)應(yīng)用,該應(yīng)用程序必須按順序重新開始對(duì)要應(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)用的一部分。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)