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

2018-02-24 15:44 更新

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

設(shè)計應(yīng)用程序,使得它可以在不需要重新部署或者重新啟動應(yīng)用程序重新配置。這有助于保持可用性并減少停機時間。

背景和問題

一個主要目的為重要的應(yīng)用,如商業(yè)和企業(yè)網(wǎng)站是盡量減少停機時間以及由此引發(fā)的中斷給客戶和用戶。但是,有時有必要重新配置應(yīng)用程序改變特定行為或設(shè)置,而在部署和使用。因此,它是用于該應(yīng)用程序被設(shè)計成這樣一種方式,以允許在運行時要應(yīng)用這些配置的變化,并為應(yīng)用程序,以檢測所述變化并且盡快地應(yīng)用它們的部件的優(yōu)點。

該種要應(yīng)用可能被調(diào)整記錄,以協(xié)助與應(yīng)用程序調(diào)試問題,交換使用不同數(shù)據(jù)存儲的連接字符串,或者打開或關(guān)閉特定的部分或應(yīng)用程序的功能的粒度配置變化的例子。

解決方案

為實施這一模式的解決方案依賴于應(yīng)用程序托管環(huán)境中可用的功能。典型地,應(yīng)用程序代碼將響應(yīng)于由檢測到的變化對應(yīng)用程序配置時,主機基礎(chǔ)設(shè)施提出的一個或多個事件。這通常是上載新的配置文件,或響應(yīng)于改變通過管理門戶的配置或者通過訪問的API的結(jié)果。

碼處理的配置變化事件可以檢查變化,并將其應(yīng)用到該應(yīng)用程序的組件。有必要對這些部件進行檢測和反應(yīng)的變化,因此它們的值通常會被公開為可寫的屬性或方法,在事件處理程序的代碼可以設(shè)置為新值,或執(zhí)行。從這一點來說,該部件應(yīng)使用新的值,以便在需要改變應(yīng)用程序的行為發(fā)生。

如果這是不可能的部件,以應(yīng)用更改在運行時,這將是必要的,重新啟動該應(yīng)用程序,從而當應(yīng)用程序啟動時再次這些更改應(yīng)用。在一些托管環(huán)境中它可能會檢測到這些類型的變化,并指出對環(huán)境的應(yīng)用程序必須重新啟動。在其他情況下,可能有必要執(zhí)行該分析的設(shè)置更改,并強制必要的應(yīng)用程序重新啟動時的代碼。

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

圖1 - 此模式的基本概述

大多數(shù)環(huán)境中暴露響應(yīng)配置更改引發(fā)的事件。在那些不這樣做,定期檢查更改配置并應(yīng)用這些變化將是必要的輪詢機制。它也可能有必要重新啟動應(yīng)用程序,如果變化不能在運行時被應(yīng)用。例如,有可能以比較在預(yù)設(shè)的時間間隔一個配置文件的日期和時間,并運行代碼以應(yīng)用更改時的較新版本中找到。另一種方法是,其中包含一個控制中的應(yīng)用程序的管理用戶界面,或使一個安全端點可以從應(yīng)用程序外部進行訪問,其執(zhí)行讀取,并應(yīng)用更新的配置的代碼。

或者,該應(yīng)用程序可以反應(yīng)以在環(huán)境中的一些其他變化。例如,發(fā)生于特定的運行時錯誤可能會改變?nèi)罩九渲米詣邮占嗟男畔?,或者代碼可以使用當前日期讀取和應(yīng)用主題,反映了季節(jié)或特殊事件。

問題和注意事項

在決定如何實現(xiàn)這個模式時,請考慮以下幾點:

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

何時使用這個模式

這種模式非常適合于:

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

這種模式可能不是合適的,如果運行時組件的設(shè)計使得它們只能在初始化時被配置,并更新這些部件的努力不能相比,重新啟動應(yīng)用程序和持久的一個短的停機時間是合理的。

例子

微軟 Azure 云服務(wù)的角色發(fā)現(xiàn)和揭露被提了兩個事件,當主機環(huán)境檢測變化的 ServiceConfiguration.cscfg 文件:

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

當取消在 RoleEnvironment.Changing 事件改變要表示到 Azure,一個新的設(shè)置不能被應(yīng)用于該應(yīng)用程序正在運行時,并且它必須以使用新的值被重新啟動。有效地,你會取消更改只有在您的應(yīng)用程序或組件無法反應(yīng)在運行時改變,需要重新啟動才能使用新的值。

注意: 欲了解更多信息,請參閱 RoleEnvironment.Changing 事件并使用 RoleEnvironment.Changing 事件 MSDN 上。

處理 RoleEnvironment.Changing 和 RoleEnvironment.Changed 事件,你通常會添加一個自定義處理該事件。例如,從你可以下載本手冊的例子運行時重新配置的解決方案的 Global.asax.cs 類下面的代碼顯示了如何添加一個名為 RoleEnvironment_Changed 到事件處理鏈中的自定義函數(shù)。這是從實施例的的 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();  
}

要注意的是,在網(wǎng)頁的角色的情況下,所述的 OnStart 事件處理程序中從 Web 應(yīng)用程序本身的單獨進程中運行。這就是為什么你通常會處理在 Global.asax 文件中 RoleEnvironment.Changed 事件處理程序,讓您可以更新您的 Web 應(yīng)用程序的運行時配置,而 RoleEnvironment.Changing 事件中的角色本身。在輔助角色的情況下,您可以訂閱雙方 RoleEnvironment.Changing和RoleEnvironment.Changed 的 OnStart 事件處理程序中的事件。

注意: 可以在服務(wù)配置文件中存儲自定義的配置設(shè)置,在自定義配置文件,在數(shù)據(jù)庫中,如在虛擬機中的 Azure SQ L數(shù)據(jù)庫或 SQL Server,或者在天青 blob 和表存儲。您需要創(chuàng)建一個可以訪問自定義配置設(shè)置和應(yīng)用程序內(nèi)設(shè)置組件的屬性,這些適用于應(yīng)用程序通常代碼。

例如,下面的自定義函數(shù)讀取設(shè)置,其名稱作為參數(shù)傳遞,從 Azure 的服務(wù)配置文件中的值,然后將它應(yīng)用到一個名為 SomeRuntimeComponent 運行時組件的當前實例。這是從實施例的的 Global.asax.cs 文件

private static void ConfigureFromSetting(string settingName)  
{  
  var value = RoleEnvironment.GetConfigurationSettingValue(settingName);  
  SomeRuntimeComponent.Instance.CurrentValue = value;  
}

注意

一些配置設(shè)置,如那些用于 Windows 標識框架,不能存儲在 Azure 服務(wù)配置文件中,并且必須在 App.config 或 Web.config 文件。

在Azure中,一些配置的變化檢測,并自動應(yīng)用。這包括在 Diagnostics.wadcfg 文件寡婦天青診斷系統(tǒng),它指定的信息類型來收集和如何保持日志文件的結(jié)構(gòu)。因此,它僅需要編寫處理添加到服務(wù)配置文件的自定義設(shè)置的代碼。你的代碼應(yīng)該:

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

例如,從你可以下載本手冊的例子運行時重新配置的解決方案 WebRole.cs 類下面的代碼顯示了如何使用 RoleEnvironment.Changing 事件取消所有設(shè)置的更新,除了可應(yīng)用于那些在運行時,不需要重新啟動。此示例允許在運行時應(yīng)用無需重新啟動應(yīng)用程序(使用此設(shè)置將能夠讀取新的值,并相應(yīng)地在運行時改變其行為的組成部分)更改為“CustomSetting”的設(shè)置。任何其他更改的配置將自動使網(wǎ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īng)用程序代碼不知道任何設(shè)置(因此不能確保它可以在運行時應(yīng)用)將導(dǎo)致重新啟動。如果更改任何一個被取消,該角色將被重新啟動。

然后可以檢測到并應(yīng)用于應(yīng)用程序的組件的新的配置后已被接受由 Azure 的框架更新未在 RoleEnvironment.Changing 事件處理程序取消。例如,在該示例解決方案的 Global.asax 文件以下代碼處理 RoleEnvironment.Changed 事件。它檢查每個配置設(shè)置,并且當它找到名為“CustomSetting”的設(shè)置,調(diào)用一個函數(shù)(前面所示),該應(yīng)用新的設(shè)置,以在應(yī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)用程序組件,那么更改將不會生效的下一次重新啟動應(yīng)用程序之前。這可能會導(dǎo)致不可預(yù)測的行為,尤其是當所述宿主角色實例由 Azure 的自動重啟在其日常維護操作,在該點的新的設(shè)定值將被應(yīng)用的一部分。

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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號