【发布时间】:2012-11-14 22:41:54
【问题描述】:
我已经阅读了this、this、this 和 this 以及其他十几个帖子/博客。
我在共享主机中有一个经常回收的 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");
}
我们的日志文件中充斥着“APPLICATION STARTING”条目,但在这些自发重启期间,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 Memory Profiler,但似乎无法找到罪魁祸首。我们还使用 dev 中附加的调试器运行它,以检查生成的线程中是否存在可能导致应用中止的未捕获异常。
我的问题是:
- 如何有效地监控共享主机中的内存使用情况,以了解我的应用程序在应用程序回收之前消耗了多少?
- 为什么没有调用 global.asax 中的 Application_[End/OnEnd/Error] 处理程序?
- 我还能如何确定导致这些循环的原因?
谢谢。
编辑:基于@Jani Hyytiäinen 的回答
场景: 线程#1 开始,然后是线程#2。线程 #1 达到内存限制但继续处理。线程#3 开始。线程 #1 完成,但 #2 在 #1 达到内存限制后处理超过 60 秒。
然后池不优雅地中止? #2 和 #3 将收到哪些 http 响应(这些是 AJAX 调用,但我在 Fiddler 中收到 504 错误)?
#3 的请求是否被接受,还是只是排队等待新池启动?
有什么方法可以知道内存限制已经达到或即将达到?
欢迎任何策略。
【问题讨论】:
-
您的站点实际上并未返回 HTTP 504 网关超时,因为该错误本身意味着 url 请求的资源没有及时响应。在您的情况下,可能是因为应用程序池已关闭而新的尚未启动。当应用程序池关闭时,其中的所有线程都将随之中止。这绝对会导致线程 #2 和 #3 上的 HTTP 504
标签: asp.net iis memory-management