2011-12-29 24 views
4

我剛剛將我的ASP.NET MVC3 Web應用程序啓動到生產環境,但是,作爲一個複雜的應用程序,啓動時需要LONG時間。顯然,我不希望我的用戶在AppPool超時之後等待一分鐘以上的第一次請求。在Azure上增加AppPool超時的優點/缺點

從我的研究,我發現有打擊這兩種方式:

運行輔助角色或其他工藝 - 這是民意調查的網站每19分鐘防止熱身。

更改默認20分鐘的超時時間 - 更大一些。

由於解決方案2似乎是更好的想法,我只是想知道這樣做的缺點是什麼,我會用完內存等?

謝謝。

回答

1

就我個人而言,我會改變超時時間,但兩者都應該工作:實際上,它們都具有防止工作進程關閉的效果。

我相信超時是爲了避免IIS保留那些很少使用的Web站點服務器所不需要的資源。鑑於大量使用的網站(如這個!)不關閉他們的工作進程,我不認爲你會看到任何內存問題。

+0

如果不需要回收他們的IIS工作進程,我也不需要!謝謝,我會繼續這樣做。 – 2011-12-30 14:07:47

3

您可以使用IIS的自動啓動功能嗎?有一個帖子here提出了這個想法。

您將擁有帶有Azure OS系列2的IIS 7.5和Win2k8 R2。您只需要能夠腳本/自動執行任何設置步驟和配置即可。

+0

非常感謝!我從來沒有聽說過這個新的自動啓動功能。我想我會用這個結合延長超時時間來達到最佳性能。 – 2011-12-30 14:06:57

2

我使用一個後臺線程來執行此操作,該後臺線程每隔15分鐘請求一次Keepalive URL。這不僅會讓應用程序閒置,還會在Web角色或虛擬機重新啓動或重建時立即啓動應用程序。

這一切都是可能的,因爲Web角色真的只是工人角色,也可以做IIS的東西。因此,您仍然可以在Web角色中使用所有標準的工作角色啓動掛鉤。

我從this blog post得到了想法,但調整了代碼來做一些額外的熱身任務。

首先,我必須從RoleEntryPoint繼承(它做一些其他的事情,除了這個熱身任務,我把他們趕走了簡單)一類:

public class WebRole : RoleEntryPoint 
{ 
    // other unrelated member variables appear here... 

    private WarmUp _warmUp; 

    public override bool OnStart() 
    { 

     // other startup stuff appears here... 

     _warmUp = new WarmUp(); 
     _warmUp.Start(); 
     return base.OnStart(); 
    } 
} 

所有實際熱身邏輯在這個熱身類。當它第一次運行時,它會在本地實例IP地址(相對於公共,負載平衡的主機名)上點擊一些URL來獲取內存中的內容,以便第一批使用它的用戶獲得儘可能快的響應時間。然後,它會循環訪問單個保持活動的URL(同樣在本地角色實例上),它不會做任何工作,只是用來確保IIS不會將應用程序池關閉爲空閒狀態。

public class WarmUp 
{ 
    private Thread worker; 

    public void Start() 
    { 
     worker = new Thread(new ThreadStart(Run)); 
     worker.IsBackground = true; 
     worker.Start(); 
    } 

    private void Run() 
    { 
     var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["http"]; // "http" has to match the endpointName in your ServiceDefinition.csdef file. 

     var pages = new string[] 
     { 
      "/", 
      "/help", 
      "/signin", 
      "/register", 
      "/faqs" 
     }; 

     foreach (var page in pages) 
     { 
      try 
      { 
       var address = String.Format("{0}://{1}:{2}{3}", 
        endpoint.Protocol, 
        endpoint.IPEndpoint.Address, 
        endpoint.IPEndpoint.Port, 
        page); 
       var webClient = new WebClient(); 
       webClient.DownloadString(address); 
       Debug.WriteLine(string.Format("Warmed {0}", address)); 
      } 
      catch (Exception ex) 
      { 
       Debug.WriteLine(ex.ToString()); 
      } 
     } 

     var keepalive = String.Format("{0}://{1}:{2}{3}", 
      endpoint.Protocol, 
      endpoint.IPEndpoint.Address, 
      endpoint.IPEndpoint.Port, 
      "/keepalive"); 

     while (true) 
     { 
      try 
      { 
       var webClient = new WebClient(); 
       webClient.DownloadString(keepalive); 
       Debug.WriteLine(string.Format("Pinged {0}", keepalive)); 
      } 
      catch (Exception ex) 
      { 
       //absorb 
      } 
      Thread.Sleep(900000); // 15 minutes 
     } 
    } 
}