2011-02-22 89 views
2

我創建了一個C#應用程序,使用Microsoft.Web.Administration.ApplicationPool類一次一個地回收IIS中的所有應用程序池。 ApplicationPool上沒有任何方法來重新啓動應用程序池(如果我錯了,請糾正我),所以我想你只需要停下來,然後開始。這在大部分情況下工作正常,直到我們開始在一個陷入無限循環的應用程序池中獲得一些線程。以編程方式回收IIS7中的應用程序池問題

默認情況下,IIS有90秒的「關閉時間限制」,在它終止任何線程仍在運行之前等待90秒,所以我會調用ApplicationPool.Stop(),並且需要90秒,直到IIS終止應用程序池,它的狀態之前將停止,我可以告訴它重新開始。任何嘗試使用該應用程序池的任何應用程序都會嘗試觸發這些應用程序池的錯誤響應,直到我可以再次啓動該池爲止。

我決定嘗試以編程方式將「關機時間限制」更改爲5秒,以減少可能會出現503錯誤的應用程序數量,但IIS在終止應用程序池之前仍等待90秒。下面是我的功能來關閉應用程序池:

private void StopAppPool(ApplicationPool applicationPool) 
{ 
    ObjectState state = applicationPool.State; 
    TimeSpan previousShutdownTimeLimit = applicationPool.ProcessModel.ShutdownTimeLimit; 
    applicationPool.ProcessModel.ShutdownTimeLimit = new TimeSpan(0, 0, 5); 
    switch (state) 
    { 
     case ObjectState.Started: 
      applicationPool.Stop(); 
      WL("Application Pool {0}'s state has gone from {1} to {2}", applicationPool.Name, state, applicationPool.State); 
      break; 
     case ObjectState.Starting: 
     case ObjectState.Unknown: 
      for (int i = 0; i < 180; i++) 
      { 
       WL("Application Pool {0}'s state is {1}. Waiting for state to become Started", applicationPool.Name, state); 
       Thread.Sleep(500); 
       state = applicationPool.State; 
       if (applicationPool.State == ObjectState.Started) { break; } 
      } 
      if (state == ObjectState.Started) 
      { 
       applicationPool.Start(); 
       WL("Application Pool {0}'s state has gone from {1} to {2}", applicationPool.Name, state, applicationPool.State); 
      } 
      else 
      { 
       WL("Error starting Application Pool {0}: Application Pool never stopped", applicationPool.Name); 
      } 

      break; 
     case ObjectState.Stopped: 
     case ObjectState.Stopping: 
      WL("Application Pool {0} was already in a {1} state and has not been modified", applicationPool.Name, state); 
      break; 
     default: 
      WL("Error stopping Application Pool {0}: Unexpected ObjectState \"{1}\"", applicationPool.Name, state); 
      break; 
    } 

    state = applicationPool.State; 
    for (int i = 0; i < 180 && state != ObjectState.Stopped; i++) 
    { 
     WL("Application Pool {0}'s state is {1}. Waiting for state to become Stopped", applicationPool.Name, state); 
     Thread.Sleep(500); 
     state = applicationPool.State; 
    } 
    applicationPool.ProcessModel.ShutdownTimeLimit = previousShutdownTimeLimit; 
}  

爲什麼不ApplicationPool.ProcessModel.ShutdownTimeLimit似乎影響所花費IIS實際上殺害的應用程序池多久?無論如何,當我試圖回收應用程序池時,讓其他應用程序無法接收503錯誤?

+0

你可能不希望聽到這些,但爲什麼在地球上,你會要回收的應用程序池? – 2011-02-23 23:01:40

回答

2

要在應用程序池上重新啓動,可以使用Recycle方法。這可能不會緩解90秒的問題。您可以在Recycling對象中使用某些東西來調整超時。

+1

把這一個算作民主。我一直在尋找重新啓動,而不是回收!但回收仍然不會更新狀態,並且更改ShutdownTimeLimit似乎不會執行任何操作。 – Daryl 2011-02-23 19:27:41

+1

當您更改ShutdownTimeLimit,你可能也必須調用ServerManager的對象上的CommitChanges:http://msdn.microsoft.com/en-us/library/microsoft.web.administration.servermanager.commitchanges(v=VS.90 ).aspx – 2011-02-23 20:02:26

7

John Koerner的回答無疑幫助我指出了正確的方向。使用回收消除503錯誤。訣竅是如何殺死無限循環。

這裏是你必須爲了使回收的應用程序池的步驟來終止該進程,服從ApplicationPool.ProcessModel.ShutdownTimeLimit屬性:通過ApplicationPools

  1. 創建ServerManager的對象
  2. 循環在ServerManager對象上,直到找到您關心的appPool。提示:ApplicationPools.First(P => p.Name == 「默認應用」)是您的ServerManager的對象上一個有用的功能
  3. 更新ApplicationPool.ProcessModel.ShutdownTimeLimit
  4. 要調用CommitChanges()。 注意:您提交更改的ServerManager對象必須是您用來獲取ApplicationPool對象的對象,並且您已對其進行更改。你不能只是做新的ServerManger()。CommitChanges();
  5. 睡一會兒,配置值將在IIS中讀取。此時,你應該可以看到在IIS
  6. 的ApplicationPool值變化
  7. 呼叫回收或停止在ApplicationPool

在回收利用的ApplicationPool,IIS是在一個新的w3wp.exe ApplicationPool進程有種異樣將立即啓動,但舊的應用程序池將等待ApplicationPool.ProcessModel.ShutdownTimeLimit中的秒數關閉。然後它會將仍在運行的任何東西移動到新的過程中。但是,如果您再次回收它,它將終止無限循環(在ShutdownTimeLimit中等待適當的時間之後)。

所以總結這一切,正確提交更改,恨不得生效,然後執行你的循環,然後再做一次,如果你有,你想殺死一個無限循環。

我已經貼在我的博客的源代碼,並最終可執行here