8

私はこれこれこれ、そしてこれに加えて他の十数の投稿/ブログを読みました。

頻繁にリサイクルされている共有ホスティングにASP.Netアプリがあります。NLogを使用し、global.asaxに次のコードがあります

void Application_Start(object sender, EventArgs e) 
{
    NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
    logger.Debug("\r\n\r\nAPPLICATION STARTING\r\n\r\n");
}
protected void Application_OnEnd(Object sender, EventArgs e)
{
    NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
    logger.Debug("\r\n\r\nAPPLICATION_OnEnd\r\n\r\n");
}

void Application_End(object sender, EventArgs e) 
{
        HttpRuntime runtime = (HttpRuntime)typeof(System.Web.HttpRuntime).InvokeMember("_theRuntime", BindingFlags.NonPublic  | BindingFlags.Static  | BindingFlags.GetField,  null,  null,  null);

if (runtime == null)
    return;

string shutDownMessage = (string)runtime.GetType().InvokeMember("_shutDownMessage",  BindingFlags.NonPublic  | BindingFlags.Instance  | BindingFlags.GetField,  null,  runtime,  null);

string shutDownStack = (string)runtime.GetType().InvokeMember("_shutDownStack",   BindingFlags.NonPublic  | BindingFlags.Instance  | BindingFlags.GetField,  null,  runtime,  null);

ApplicationShutdownReason shutdownReason = System.Web.Hosting.HostingEnvironment.ShutdownReason;

NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
logger.Debug(String.Format("\r\n\r\nAPPLICATION END\r\n\r\n_shutDownReason = {2}\r\n\r\n _shutDownMessage = {0}\r\n\r\n_shutDownStack = {1}\r\n\r\n",
                shutDownMessage, shutDownStack, shutdownReason));
}

void Application_Error(object sender, EventArgs e) 
{
    NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
    logger.Debug("\r\n\r\nApplication_Error\r\n\r\n");

}

ログファイルには「APPLICATIONSTARTING」エントリが散らばっていますが、Application_OnEndこれらの自発的な再起動中に、、、または起動されることはApplication_Endありません。Application_Errorweb.configファイルまたは/binファイルにアクセスするためのエントリがあるため、これらが機能していることはわかっています。また、メモリ過負荷テストを実行し、OutOfMemoryExceptionでキャッチされたをトリガーできApplication_Errorます。

仮想メモリの制限がリサイクルの原因であるかどうかを判断しようとしています。GC.GetTotalMemory(false)コード全体に追加しましたが、これはアプリのプールだけでなく、すべての.Netに当てはまります。私たちも試しました

var oPerfCounter = new PerformanceCounter();
oPerfCounter.CategoryName = "Process";
oPerfCounter.CounterName = "Virtual Bytes";
oPerfCounter.InstanceName = "iisExpress";
logger.Debug("Virtual Bytes: " + oPerfCounter.RawValue + " bytes");

ただし、共有ホスティングの権限はありません。

ANTSメモリプロファイラーが接続された本番環境でリサイクルを引き起こしたのと同じリクエストで開発サーバー上のアプリを監視しましたが、原因を見つけることができないようです。また、devにアタッチされたデバッガーを使用して実行し、アプリが異常終了する可能性のある、生成されたスレッドでキャッチされない例外をチェックしました。

私の質問は次のとおりです。

  • 共有ホスティングのメモリ使用量を効果的に監視して、アプリケーションをリサイクルする前にアプリケーションがどれだけ消費しているかを知るにはどうすればよいですか?
  • global.asaxのApplication_[End/ OnEnd / Error]ハンドラーが呼び出されないのはなぜですか?
  • これらのリサイクルの原因を他にどのように特定できますか?

ありがとう。

編集:@JaniHyytiäinenによる回答に基づく

シナリオ:スレッド#1が始まり、スレッド#2が続きます。スレッド#1はメモリ制限に達しましたが、処理を続行します。スレッド#3が始まります。スレッド#1は終了しますが、#1がメモリ制限に達してから#2は60秒以上処理します。

その後、プールは不当に中止しますか?#2と#3はどのようなhttp応答を受け取りますか(これらはAJAX呼び出しですが、Fiddlerで504エラーが発生します)?
#3のリクエストは受け入れられますか、それとも新しいプールが起動するまでキューに入れられますか?
メモリ制限に達した、またはこれから迫っていることを知る方法はありますか?

どんな戦略も歓迎します。

4

3 に答える 3

16

iisにはアプリケーションプールのシャットダウン時間制限があります。60秒で、共有ホスティング環境にアプリケーションプールのメモリ制限があるとします。アプリケーションプールがこの制限に達し、iisはアプリケーションプールに現在の要求ですべての作業を終了するように指示します。60秒が経過する前にすべてのリクエストの処理が完了すると、application_endがトリガーされ、アプリケーションプールが正常にシャットダウンします。ただし、60秒が経過しても要求がまだ処理されている場合、IISは動揺し、アプリプールを強制終了します。今回は、application_endはトリガーされません。同様に、エラーイベントハンドラーはトリガーされません。

于 2012-11-14T23:04:02.230 に答える
0

シャットダウンイベントを正しく発生させるアプリケーションの1つを調べました。これが、Global.asax.csのシグネチャです。

protected void Application_End(object sender, EventArgs e)
{
    ApplicationShutdownReason shutdownReason = System.Web.Hosting.HostingEnvironment.ShutdownReason;
    // Write to log
}

私が気付いた唯一の違いは、「Application_End」メソッドと「Application_Error」メソッドに「protected」修飾子がないことです。リフレクションがプライベートメンバーで機能しない状況をたくさん見たので、それが機能している可能性があります。

また、ローカル/開発アプリケーションプールのアイドルタイムアウトを低い値(1分など)に設定してから、Application_Endイベントがローカルで発生することを確認してください。

デフォルトでは、IISアプリケーションプールは要求がない状態で20分後にリサイクルされるため、トラフィックの少ないアプリケーションを使用している場合は、これに遭遇する可能性があることに注意してください。また、一部の共有ホスティングプロバイダーは、リソースを節約するために、この「アイドルタイムアウト」値を低く変更します。

于 2012-11-14T22:57:27.557 に答える
0

使用しているIISのバージョンはわかりませんが、IIS7.5には、アプリプールのリサイクルの理由をログに記録できるアプリプールリサイクルイベントログ設定が多数あります。

IISで、[アプリケーションプール]に移動し、問題のアプリプールの[詳細設定]に移動します。リサイクルに移動すると、「リサイクルイベントログエントリの生成」というサブメニューがあります。

于 2013-05-28T07:59:43.243 に答える