簡體   English   中英

加載緩存時如何平衡Azure Cloud Services WebRoles

[英]How do you load balance Azure Cloud Services WebRoles when loading a cache

鑒於部署到Azure的雲服務WebRoles(2)在.NET 4.5.2和OS家庭“4”(視窗2012)使用Azure的SDK 3.0。

Web應用程序啟動時,我們想加載大約10分鍾的緩存(從Blob存儲中加載)(我們已經研究過移動它,但目前無法這樣做)

然后,當IIS應用程序池回收時,我們希望該站點保持正常運行。

當前,Cloud Services的默認IIS設置為:

  • 不在加載時啟動(autoStart / startMode)
  • 每20分鍾空閑一次(idleTimeout)
  • 每29小時循環一次(periodicRestart)
  • 作為HTTP 503失敗(loadBalancerCapabilities)

因為我們默認使用2 WebHost,所以我們想在不同時間回收應用程序池。 理想情況下,如果其中一個Web主機正在加載緩存,則我們希望重定向來自站點的現有連接。

到目前為止,我們已經有了一個啟動任務腳本來重新配置IIS AppPools

appcmd set config -section:system.applicationHost/applicationPools 

  /applicationPoolDefaults.autoStart:"True"
  /applicationPoolDefaults.startMode:"AlwaysRunning"
  /applicationPoolDefaults.processModel.idleTimeout:"00:00:00" 
  /applicationPoolDefaults.recycling.logEventOnRecycle:"Time,Requests,Schedule,Memory,IsapiUnhealthy,OnDemand,ConfigChange,PrivateMemory"
  /applicationPoolDefaults.recycling.periodicRestart.time:"00:00:00" 
  /~"applicationPoolDefaults.recycling.periodicRestart.schedule" 
  /+"applicationPoolDefaults.recycling.periodicRestart.schedule.[value='06:00:00']" 
  /applicationPoolDefaults.failure.loadBalancerCapabilities:"TcpLevel" 

例如

%windir%\system32\inetsrv\appcmd set config -section:applicationPools /applicationPoolDefaults.autoStart:"True" /commit:apphost

至於代碼,我們一直在使用Busy標志,直到緩存加載完畢。 這似乎並未重新引導流量

RoleEnvironment.StatusCheck += WebRoleEnvironment_StatusCheck;

        if (Busy)
        {
            e.SetBusy();
        }

缺點是,由於需要容器,因此在Application_Start完成此操作。 我認為將LoadCache()移到LoadCache()OnStart()RoleEntryPoint

注意; 默認情況下,我們還啟用了“保持活動”。

問題;

  1. 在加載緩存時,我們如何使WebHost脫機?
  2. 我們應該更改IIS設置嗎? https://azure.microsoft.com/en-gb/blog/iis-reset-on-windows-azure-web-role/
  3. 我們應該使用IIS 8.0應用程序初始化嗎? http://fabriccontroller.net/iis-8-0-application-initialization-module-in-a-windows-azure-web-role/
  4. 應該將loadBalancerCapabilities設置為什么? https://docs.microsoft.com/en-us/iis/configuration/system.applicationhost/applicationpools/add/failure
  5. 我們應該嘗試錯開回收嗎? 當我們擴展(添加更多實例) 時該怎么辦?azure是否會阻止角色實例同時被回收?

請參閱https://blogs.msdn.microsoft.com/kwill/2012/09/19/role-instance-restarts-due-to-os-upgrades/ ,特別是常見問題#5:

如果您的網站需要幾分鍾的時間進行預熱(對預編譯和模塊加載進行標准IIS / ASP.NET預熱,或者對緩存或其他特定於應用程序的任務進行預熱),則您的客戶端可能會遇到中斷或隨機超時的情況。 角色實例重新啟動並且您的OnStart代碼完成之后,您的角色實例將被放回負載平衡器循環中,並開始接收傳入的請求。 如果您的網站仍在預熱,則所有這些傳入請求都將排隊並超時。 如果您只有2個Web角色實例,則IN_0(仍在預熱中)將在重新啟動IN_1進行Guest OS更新時接收100%的傳入請求。 這可能導致您的服務完全中斷,直到您的網站在兩個實例上均完成預熱為止。 建議將您的實例保持在OnStart上,這將使其保持在“忙”狀態,在此狀態下,它不會從負載平衡器接收傳入的請求,直到您的預熱完成為止。 您可以使用以下代碼來完成此操作:

 public class WebRole : RoleEntryPoint {  
   public override bool OnStart () {  
     // For information on handling configuration changes  
     // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.  
     IPHostEntry ipEntry = Dns.GetHostEntry (Dns.GetHostName ());  
     string ip = null;  
     foreach (IPAddress ipaddress in ipEntry.AddressList) {  
       if (ipaddress.AddressFamily.ToString () == "InterNetwork") {  
         ip = ipaddress.ToString ();  
       }  
     }  
     string urlToPing = "http://" + ip;  
     HttpWebRequest req = HttpWebRequest.Create (urlToPing) as HttpWebRequest;  
     WebResponse resp = req.GetResponse ();  
     return base.OnStart ();  
   }  
 }  

根據您的描述,根據我的理解和經驗,我認為在當前場景中滿足您的所有需求幾乎是不可能的,因為當前需求需要在體系結構上進行更改。

這是我的想法如下。

  1. 我猜緩存blob文件太大,這導致需要更多時間從blob存儲中加載緩存。 這樣可以減少時間成本。 我認為解決方案是將使用情況統計信息將緩存blob文件拆分為多個較小的文件,並同時加載它們,或者使用表存儲而不是blob存儲作為L2緩存,只需從表存儲中查詢緩存數據並將其存儲到內存中即可作為具有到期時間的L1緩存,即使您可以使用Azure Redis緩存來存儲緩存數據也比表存儲更快。
  2. 確保存在用於keep-alive連接的重試機制。 然后,當某個角色實例停止或重新啟動時,現有連接將重定向到另一個角色實例。
  3. 要實現用於重新啟動角色實例的功能,可以使用REST API 重新啟動角色實例

希望能幫助到你。

這就是我們最終得到的結果:

編輯 :更改為HttpWebRequest因此支持重定向

a)部署VM /修補OS后,我們在OnStart()輪詢httpsIn端點

public class WebRole : RoleEntryPoint
{
    public override bool OnStart()
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

        // Note: the Web Requests all run in IIS, not from this process.
        // So, we aren't disabling certs globally, just for checks against our own endpoint.
        ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true;

        var address = GetAddress("httpIn");

        var request = (HttpWebRequest)WebRequest.Create(address);
        request.MaximumAutomaticRedirections = 1;
        request.AllowAutoRedirect = false;
        var response = request.GetResponse() as HttpWebResponse;
        //_logger.WriteEventLog($"Response: '{response?.StatusCode}'");
        return base.OnStart();
    }

    static Uri GetAddress(string endpointName)
    {
        var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[endpointName];
        var address = $"{endpoint.Protocol}://{endpoint.IPEndpoint.Address}:{endpoint.IPEndpoint.Port}";
        return new Uri(address);
    }
}

b)對於AppPool回收,我們在Global.asax中報告忙

public class RoleEnvironmentReadyCheck
{
    bool _isBusy = true;

    public RoleEnvironmentReadyCheck()
    {
        RoleEnvironment.StatusCheck += RoleEnvironment_StatusCheck;
    }

    void RoleEnvironment_StatusCheck(object sender, RoleInstanceStatusCheckEventArgs e)
    {
        if (_isBusy)
        {
            e.SetBusy();
        }
    }

    public void SetReady()
    {
        _isBusy = false;
    }
}

public class WebApiApplication : HttpApplication
{
    protected void Application_Start()
    {
        var roleStatusCheck = new RoleEnvironmentReadyCheck();
        //SuperLoadCache()
        roleStatusCheck.SetReady();
    }
}

c)對於AppPool回收,我們選擇一天中的某個時間(03:00 AM),並將角色錯開30分鍾,並在PowerShell腳本ConfigureIIS.ps1中停止空閑超時。

$InstanceId = $env:INSTANCEID
$role = ($InstanceId -split '_')[-1]
$roleId = [int]$role
$gapInMinutes = 30
$startTime = New-TimeSpan -Hours 3
$offset = New-TimeSpan -Minutes ($gapInMinutes * $roleId)
$time = $startTime + $offset
$timeInDay = "{0:hh\:mm\:ss}" -f $time

Write-Host "ConfigureIIS with role: $role to $timeInDay"

& $env:windir\system32\inetsrv\appcmd set config -section:system.applicationHost/applicationPools /applicationPoolDefaults.processModel.idleTimeout:"00:00:00" /commit:apphost
& $env:windir\system32\inetsrv\appcmd set config -section:system.applicationHost/applicationPools /applicationPoolDefaults.recycling.logEventOnRecycle:"Time,Requests,Schedule,Memory,IsapiUnhealthy,OnDemand,ConfigChange,PrivateMemory" /commit:apphost
& $env:windir\system32\inetsrv\appcmd set config -section:system.applicationHost/applicationPools /applicationPoolDefaults.recycling.periodicRestart.time:"00:00:00" /commit:apphost
& $env:windir\system32\inetsrv\appcmd set config -section:system.applicationHost/applicationPools /~"applicationPoolDefaults.recycling.periodicRestart.schedule" /commit:apphost
& $env:windir\system32\inetsrv\appcmd set config -section:system.applicationHost/applicationPools /+"applicationPoolDefaults.recycling.periodicRestart.schedule.[value='$timeInDay']" /commit:apphost

並將RoleId傳遞到ConfigureIIS.cmd

PowerShell -ExecutionPolicy Unrestricted .\ConfigureIIS.ps1 >> "%TEMP%\StartupLog.txt" 2>&1

EXIT /B 0

ServiceDefinition.csdef中設置

 <Task commandLine="ConfigureIIS.cmd" executionContext="elevated" taskType="simple">
    <Environment>
      <Variable name="INSTANCEID">
        <RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/@id"/>
      </Variable>
    </Environment>
  </Task>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM