2011-02-22 86 views
2

Microsoft.Web.Administration.ApplicationPoolクラスを使用して、IISですべてのアプリケーションプールを一度に1つずつリサイクルするC#アプリケーションを作成しました。 ApplicationPoolにはアプリケーションプールを再起動する方法はありません(私が間違っていれば私を修正してください)。だから私はあなたがちょうど停止してから始める必要があると考えました。無限ループに陥っていたスレッドをアプリケーションプールに入れ始めるまで、これはほとんどの場合うまくいきました。IIS7でアプリケーションプールをプログラムでリサイクルする問題

既定では、IISには90秒間の「シャットダウン時間制限」があり、実行中のスレッドが終了するまでに90秒間待機するため、ApplicationPool.Stop()を呼び出すとIIS終了まで90秒かかりますそれが状態になる前にアプリケーションプールを停止し、私はそれが再び始まるように指示することができます。そのアプリケーションプールを使用しているアプリケーションにヒットしようとするものは、プールを再開するまで、90秒間、503エラー応答が返されます。

「シャットダウン時間制限」をプログラムで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

あなたはおそらくこれを聞きたくありませんが、なぜ地球上でアプリケーションプールをリサイクルしたいですか? –

答えて

2

アプリケーションプールで再起動するには、Recycleメソッドを使用できます。それはおそらく90秒の問題を緩和しません。 Recyclingオブジェクトに、タイムアウトを調整するために再生できるものがあります。

+1

この1つを卑劣なものとして数えます。私はリサイクルではなく、再起動を探し続けました!しかし、リサイクルはまだ状態を更新せず、ShutdownTimeLimitの変更は何もしないようです。 – Daryl

+1

ShutdownTimeLimitを変更すると、ServerManagerオブジェクトのCommitChangesも呼び出す必要があります。http://msdn.microsoft.com/en-us/library/microsoft.web.administration.servermanager.commitchanges(v=VS.90) ).aspx –

7

John Koernerさんの回答は間違いなく正しい方向に向いています。リサイクルを使用すると、503のエラーが削除されます。トリックは、無限ループをどのように殺すかでした。ここで

あなたはリサイクルアプリケーションプールのプロセスを強制終了し、ApplicationPool.ProcessModel.ShutdownTimeLimitプロパティに従うようにするために必要な手順です:

  1. ApplicationPoolsを通じてServerManagerのオブジェクト
  2. ループを作成します。あなたが気にするappPoolが見つかるまで、ServerManagerオブジェクトにヒント:ApplicationPools.Firstた(p => p.Name == "のDefaultAppPool")便利機能です
  3. 更新ApplicationPool.ProcessModel.ShutdownTimeLimit
  4. コールCommitChangesを()あなたServerManagerのオブジェクトに。 注:変更をコミットするServerManagerオブジェクトは、変更したApplicationPoolオブジェクトを取得するために使用したオブジェクトでなければなりません。新しいServerManger()だけではできません。CommitChanges();
  5. 秒間スリープするので、IISで設定値が読み取られます。この時点で、あなたはIIS
  6. でApplicationPool上の値を変更
  7. コールリサイクルを見るべきか、

はApplicationPoolをリサイクルあなたのApplicationPoolに停止し、IISは、その新しいw3wp.exeのApplicationPoolプロセスにおける一種の奇妙ですすぐに起動しますが、古いアプリケーションプールは、ApplicationPool.ProcessModel.ShutdownTimeLimitで停止するまでの秒数を待機します。その後、まだ実行中のものはすべて新しいプロセスに移動します。しかし、もう一度リサイクルすると、無限ループが終了します(ShutdownTimeLimitで適切な時間待機した後)。

これをまとめて、変更を正しくコミットしてから、リサイクルを実行してから、無限ループで殺したい場合はもう一度やり直してください。

私のブログにはソースコードと最終実行ファイルhereが掲載されています。

+0

IISでappPoolリサイクルが発生すると、新しいプロセスが作成され、新しいすべての要求が新しいプロセスにルーティングされます。古いプロセスが実行されているため、現在実行されているすべての要求を完了してからシャットダウンすることができます。これは、すべての要求が処理され、要求が破棄されないようにするために行います。 – ulty4life

+0

@ ulty4lifeはい、実際にはそれを2回リサイクルすると実際に殺されます。それは、IISプロセス間で要求が転送された回数を追跡しているようなもので、複数回ある場合は終了します。 – Daryl

+0

素敵な仕事、私はこれに似たコードを探していて、あなたはプロセスを説明してくれました。 – SefTarbell

関連する問題