私はこれ、これ、これ、そしてこれに加えて他の十数の投稿/ブログを読みました。
頻繁にリサイクルされている共有ホスティングに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_Error
web.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のリクエストは受け入れられますか、それとも新しいプールが起動するまでキューに入れられますか?
メモリ制限に達した、またはこれから迫っていることを知る方法はありますか?
どんな戦略も歓迎します。