2017-02-20 57 views
1

正如其他各种相关问题中所述,我还期待在重新部署带有相当大EF6模型的Web角色以及大量参考的nuget之后首次调用持续(30秒) -packages。在尝试使用preloadEnabledserviceAutoStartProviders的不同建议解决方案后,我仍然很满意并决定重新开放此主题,希望有人在此期间找到更好的解决方案。部署后Az​​ure Web角色预热

对于我来说,主要目标是在角色在新部署中退出忙碌状态并可通过负载平衡器和外部客户端访问时,使Web角色以接近后续调用的速度回应第一个请求。不幸的是我经历了以下问题,目前提出的解决方案:

  1. preloadEnabled

    • 我通过PKGMGR.EXE /iu:IIS-ApplicationInit在启动任务添加应用程序初始化模块。到现在为止还挺好。
    • 当我然后尝试执行%windir%\system32\inetsrv\appcmd set site "MySiteName" -applicationDefaults.preloadEnabled:true时,它在执行启动脚本时失败,在全新部署中仍然没有在IIS中创建网站。
    • 如果我尝试通过我的Application_Start方法中的ServerManager -class设置preloadEnabled设置,我不明白,在对web角色进行第一次外部调用之前如何执行此代码作为preloadEnabled设置在新的web角色部署后默认为false,因此我理解的Application_Start方法没有机会被Application Initialization模块执行?
  2. serviceAutostartProviders

    • 这里我们需要把我们的实施中对ApplicationHost.config的IProcessHostPreloadClient接口通过使用APPCMD脚本或ServerManager的类,即AutostartProvider的名字,但:
      • serviceAutostartProvider就像preloadEnabled一个网站相关的设置,所以我们在这里有1.237中的%windir%\system32\inetsrv\appcmd set site "MySiteName" -applicationDefaults.preloadEnabled:true相同的问题 - 在全新部署后的启动脚本执行时,网站没有t尚未在IIS中创建并且脚本无法正常执行
      • 另一种可能性是将applicationhost.config包含到部署包中,但我没有找到任何解决方案来为Web角色执行此操作。

那么怎么你们管理,以确保,即预加载组件和一些初始化代码(如填充内存高速缓存)被之前运行作用得到它的第一次从外线命中?

我们现在开始获得一些流量并获得约。我们的WebApi上每秒发出1-2个请求,因此,每次更新部署之后,客户端预加载“可见”的时间延迟30秒,现在已成为主要问题。

我们在低流量时间调度更新部署,但如果我需要进行紧急修补程序部署,该怎么办?

回答

1

也许最好的方法是使用部署插槽。首先将更新部署到临时插槽。在从一个临时插槽切换到一个生产插槽之前,Kudu将通过一个请求打开临时插槽的根部,以预热该应用程序。在对分段插槽的根的请求返回之后,IP交换机发生并且您的插槽被交换。

但是,有时您需要预热其他页面或服务才能使应用程序准备好处理流量,并且用热身请求打击根目录是不够的。您可以更新您的web.config,以便Kudu在IP交换机发生并且交换插槽之前将命中额外的页面和端点。

这些预热请求URL应该在标签中。这里有一个例子:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <system.webServer> 
    <applicationInitialization> 
     <add initializationPage="/pagetowarmup1" /> 
     <add initializationPage="/pagetowarmup2" /> 
     <add initializationPage="/pagetowarmup3" /> 
    </applicationInitialization> 
    </system.webServer> 
</configuration> 

你可以在这个问题上here读库杜文档。

+0

谢谢热身实例的代码。但您的解决方案是否也适用于Web角色?据我所知,它只是一个Azure Web Apps的功能? – maxyha

0

好的。现在我懂了。

的点是设置preloadEnabled -property不内侧Global.asax中Application_Start方法(因为它不会在第一请求中的作用无论如何之前被击中)的,但内部RoleEntryPoint.OnStart

不同之处在于在部署包之后直接调用RoleEntryPoint.OnStart并且所有设置都是为了启动角色。此时,Azure实例仍处于繁忙状态,并且只要RoleEntryPoint.OnStart中的某些代码正在执行,尚未从外部获得。

因此,这里是我想出了迄今为它获得了第一次调用之前从外部

public class WebRole : RoleEntryPoint 
{ 
    public override bool OnStart() 
    { 
     // set preloadEnabled of each Site in this deployment to true 
     using (var serverManager = new ServerManager()) 
     { 
      foreach (var mainSite in serverManager.Sites) 
      { 
       var mainApplication = mainSite.Applications["/"]; 
       mainApplication["preloadEnabled"] = true; 
      } 
      serverManager.CommitChanges(); 
     } 

     // call my warmup-code which will preload caches and do some other time consuming preparation 
     var localuri = new Uri(string.Format("https://{0}/api/warmup", RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Endpoint1"].IPEndpoint)); 
     try 
     { 
      var request = (HttpWebRequest)WebRequest.Create(localuri); 
      request.Method = "GET"; 
      var response = request.GetResponse(); 
     } 
     catch { } 

     // send this thread to sleep in order to give the warmup-request a chance to complete BEFORE the Role will get started 
     // and becomes available to the outside world 
     System.Threading.Thread.Sleep(60000); 


     return base.OnStart(); 
    } 


} 
+0

在这种情况下,您正在创建的WebRequest由完全IIS创建的HttpApplication处理,而不是由执行热身代码的相同进程处理,对吗? – NStuke

相关问题