IIS6应用程序池崩溃

本文关键字:崩溃 程序池 应用程序 应用 IIS6 | 更新日期: 2023-09-27 18:08:50

在最近的压力和容量测试中,我们意识到30分钟后,所有用户都与网站断开连接。在记录事件之后,我们注意到应用程序池崩溃了。做一些谷歌调查,显然在大多数原因,这是由于未处理的异常。

所以当应用程序崩溃时,将显示以下异常详细信息:

An unhandled exception occurred and the process was terminated.
Application ID: DefaultDomain
Process ID: 7852
Exception: System.Runtime.Serialization.SerializationException
Message: Type 'FuseFarm.FrameworkException' in Assembly 'FuseFarm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
StackTrace:    at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.SerializeObject(Object obj, MemoryStream stm)
   at System.AppDomain.Serialize(Object o)
   at System.AppDomain.MarshalObject(Object o)

我不知道为什么它试图序列化FrameworkException,而且我无法在代码中看到这是在做什么。但我确实看到有几部分代码

new FrameworkException(exData, "ContractComposition.SubmitContract");

正在被调用,但没有被处理。在检查global.asax.cs之后,会发生以下情况:

protected void Application_Error(object sender, EventArgs e)
{
    ILog log = LogManager.GetLogger(typeof(Global));
    string environmentName = WebConfigurationManager.AppSettings["EnvironmentName"];
    if (!String.IsNullOrEmpty(environmentName) && (environmentName == "DEMO" || environmentName == "LIVE"))
    {
        Exception currentException = Server.GetLastError().GetBaseException();
        Session["errorMessage"] = currentException.Message;
        Session["errorSource"] = currentException.Source;
        Session["errorTrace"] = currentException.StackTrace;
        log.Error(currentException.Message, currentException);
        if (currentException != null)
        {
            Session["error"] = currentException.GetType().Name;
            switch (currentException.GetType().ToString())
            {
                case "System.ApplicationException":
                case "FuseFarm.FrameworkException":
                    break;
                default:
                    new FrameworkException(currentException.Message + "'n" + currentException.StackTrace, currentException.Source, currentException);
                    break;
            }
        }
        Server.Transfer("~/error.aspx");
    }
}

在Application_Error中抛出新的异常…这看起来不对吗?如果此时抛出这个错误,谁和什么将处理这个错误?

IIS6应用程序池崩溃

正在序列化FrameworkException,因为它试图跨越AppDomain边界。

所有穿过AppDomain的对象都必须被序列化,异常也不例外。

当一个Exception没有正确实现序列化时,你可以认为它是一个bug。

我不相信你的错误处理程序是问题的根源。考虑到堆栈跟踪,很难判断——一个完整的内存转储将产生更好的信息。

最好的办法是适当地使异常可序列化。

这可能不能完全解决你的问题——总而言之,你仍然会抛出异常。希望一旦这个问题得到纠正,您就会看到问题的真正原因。

如果Application_Error抛出异常,你的应用程序池将崩溃,就像你看到的那样。根据您所展示的代码,我可以得出如下结论:

这行中引用的错误日志记录器
log.Error(currentException.Message, currentException);

试图序列化传递给它的异常。当currentException最终为FuseFarm.FrameworkException类型时,错误处理程序在该行崩溃,并且您的应用程序池关闭。

如果是这种情况,您需要将FuseFarm.FrameworkException标记为Serializable,更改日志记录器以不尝试序列化对象,或者在Application_error处理程序中放置一个try/catch块,如果您希望应用程序池继续运行,则使用这些异常做其他事情。