我已经将在我的计算机上运行的ASP.NET MVC 3应用程序部署到shared hosting provider,并且发现了一些似乎与正在回收的应用程序池相关的问题。主机已配置在以下任何情况下进行回收:
我的开发机器上的限制更加轻松,因此在开发过程中我没有看到这样的回收。我没有管理员访问共享主机盒(可以理解),所以我无法阅读事件日志,看看为什么会发生这种回收。
有没有办法可以找出我的应用程序被回收的原因(例如Application_End
),以便我可以记录它来帮助调试?
答案 0 :(得分:11)
无法访问事件日志(因为您处于共享托管环境中),您将获得的最多信息来自Application_End
事件并询问HttpRuntime
(通过反思) )一个或两个私人成员的价值,遗憾的是没有公开曝光。
为此,请将以下代码添加到Application_End
事件中:
BindingFlags staticFlags =
BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetField;
BindingFlags instanceFlags =
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField;
HttpRuntime runtime = (HttpRuntime)typeof(System.Web.HttpRuntime)
.InvokeMember("_theRuntime", staticFlags, null, null, null);
if(runtime != null)
{
string shutDownMessage = (string)runtime.GetType()
.InvokeMember("_shutDownMessage", instanceFlags, null, runtime, null);
string shutDownStack = (string)runtime.GetType()
.InvokeMember("_shutDownStack", instanceFlags, null, runtime, null);
// Log shutDownMessage & shutDownStack somewhere
}
如果我关闭或回收我的应用程序的应用程序池,我会看到以下内容:
HostingEnvironment initiated shutdown HostingEnvironment caused shutdown - at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) at System.Environment.get_StackTrace() at System.Web.Hosting.HostingEnvironment.InitiateShutdownInternal() at System.Web.Hosting.HostingEnvironment.InitiateShutdownWithoutDemand() at System.Web.Hosting.PipelineRuntime.StopProcessing()
这可能和它一样好。
<强>更新强>
我不记得我在哪里找到了这段代码,但Drew提醒我这是来自Scott Guthrie博客文章。
还有一些其他私人成员可能很有用,例如:
private ApplicationShutdownReason _shutdownReason;
您可以在.NET Reflector中检查这些字段(如果您还有一个没有时间轰炸的副本)或其中一个备选方案(Open Source Alternatives to Reflector?)。
答案 1 :(得分:7)
首先,我尝试使用System.Web.ProcessModelInfo.GetCurrentProcessInfo()
和System.Web.ProcessModelInfo.GetHistory(int)
。这些方法的结果返回信息,例如PID,开始时间,年龄,状态和峰值内存使用情况。不幸的是,这些在我的托管环境中无法使用:
HttpException 0x80004005 - 仅当启用ASP.NET进程模型时,进程度量标准才可用。在工作进程隔离模式下运行IIS 6或更高版本时,不支持此功能。
这种方法可能适用于其他人,所以如果你处于这种情况,请试一试。
属性System.Web.Hosting.HostingEnvironment.ShutdownReason
是一个包含大量值的枚举,但不幸的是,我在问题中概述的所有案例都捆绑在一个枚举值中:
ApplicationShutdownReason.HostingEnvironment
:托管环境关闭了应用程序域。
ScottGu has an approach on his blog(代码Kev posted),它使用反射来访问HttpApplication
的内部状态。不幸的是,在这种情况下,它只报告与上面#2相同的细节:
_shutDownMessage =
HostingEnvironment initiated shutdown
HostingEnvironment caused shutdown
_shutDownStack =
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at System.Web.Hosting.HostingEnvironment.InitiateShutdownInternal()
at System.Web.Hosting.HostingEnvironment.InitiateShutdownWithoutDemand()
at System.Web.Hosting.PipelineRuntime.StopProcessing()
答案 2 :(得分:3)
以下是http://mitchelsellers.com/blogs/2007/03/15/logging-aspnet-application-restarts.aspx
的优秀代码 inner join
REZNVOD01.dbo.TimeZoneVariation tzv on tzv.TimeZoneCode = s.TimeZoneCode
and tzv.EndUTC >= BookingDate
and tzv.StartUTC <= BookingDate
答案 3 :(得分:3)
这是一个非常晚的答案,但我希望它可以为那些有类似问题(IIS 7.x或更高版本)的人提供额外的见解。
<强> 1。查找应用程序池何时开始关闭 - 以下代码可用于查找应用程序池何时开始关闭。在此事件发生后,实际关闭的最大关闭限制(秒,默认为90)。
public class ApplicationPoolService : IApplicationPoolService
{
public bool IsShuttingDown()
{
return System.Web.Hosting.HostingEnvironment.ShutdownReason != ApplicationShutdownReason.None;
}
public ApplicationShutdownReason GetShutdownReason()
{
return System.Web.Hosting.HostingEnvironment.ShutdownReason;
}
}
public class HostingEnvironmentRegisteredObject : IRegisteredObject
{
public void Stop(bool immediate)
{
// second call is done when the Stop is imminent
if (immediate)
return;
var reason = appPoolService.GetShutdownReason().ToString();
logger.Log(LogLevel.Info, $"HostingEnvironmentRegisteredObject.stop called with shutdown reason {reason}");
}
}
// this code should be placed in global.asax.cs
protected void Application_Start()
{
HostingEnvironment.RegisterObject(new HostingEnvironmentRegisteredObject());
}
这有助于找到一般原因以及确切触发的时间。在您的情况下,我认为HostingEnvironment
是值。不幸的是,根本原因并不是唯一的。它可以是定期回收,由于内存限制而回收(OP问题中最可能的原因),由于固定时间等而回收。
<强> 2。找到确切原因 - 找出确切原因的一种方法是在EventLog中搜索它。如果无法访问,可以通过提供以下详细信息来向托管服务提供商请求缩小搜索范围。
事件日志应返回更多相关信息,如下所示:
进程ID为&#39; xxx&#39;的工作进程服务应用程序池 &#39; XXX&#39;已要求回收,因为它到达了它 预定的回收时间。
进程ID为&#39; xxx&#39;的工作进程服务应用程序池 &#39; XXX&#39;已请求回收,因为它已到达其虚拟内存 限制。