对于ASP.NET应用程序,我们正在使用进程外会话提供程序(ScaleOut),我们注意到当未正确设置用于反序列化的对象无意中进入会话时,我们发现最终会导致整个过程终止。如何保护应用程序池免受会话序列化异常的影响?
重现和处理这种情况下,它变得更有趣。
终止过程中的异常在AnyStaObjectsInSessionState提出其实现是非常简单的:
internal static bool AnyStaObjectsInSessionState(HttpSessionState session)
{
if (session != null)
{
int count = session.Count;
for (int i = 0; i < count; i++)
{
object obj2 = session[i];
if (((obj2 != null) && (obj2.GetType().FullName == "System.__ComObject"))
&& (UnsafeNativeMethods.AspCompatIsApartmentComponent(obj2) != 0))
{
return true;
}
}
}
return false;
}
这里的堆栈跟踪显示异常这里如何终止进程:
An unhandled exception occurred and the process was terminated.
Application ID: /LM/W3SVC/1/ROOT
Process ID: 4208
Exception: System.Runtime.Serialization.SerializationException
Message: The constructor to deserialize an object of type 'Lucene.Net.QueryParsers.ParseException' was not found.
StackTrace: at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Web.Util.AltSerialization.ReadValueFromStream(BinaryReader reader)
at System.Web.SessionState.SessionStateItemCollection.ReadValueFromStreamWithAssert()
at System.Web.SessionState.SessionStateItemCollection.DeserializeItem(String name, Boolean check)
at System.Web.SessionState.SessionStateItemCollection.DeserializeItem(Int32 index)
at System.Web.SessionState.SessionStateItemCollection.get_Item(Int32 index)
at System.Web.SessionState.HttpSessionStateContainer.get_Item(Int32 index)
at System.Web.Util.AspCompatApplicationStep.AnyStaObjectsInSessionState(HttpSessionState session)
at System.Web.HttpApplicationFactory.FireSessionOnEnd(HttpSessionState session, Object eventSource, EventArgs eventArgs)
at System.Web.SessionState.SessionOnEndTargetWorkItem.RaiseOnEndCallback()
at System.Web.Util.WorkItem.CallCallbackWithAssert(WorkItemCallback callback)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)
InnerException: System.Runtime.Serialization.SerializationException
Message: The constructor to deserialize an object of type 'Lucene.Net.QueryParsers.ParseException' was not found.
StackTrace: at System.Runtime.Serialization.ObjectManager.GetConstructor(Type t, Type[] ctorParams)
at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
我们想了解两件事:
何时FireSessionOnEnd为进程外提供程序启动,更重要的是,我们如何在没有负载的开发环境中模拟此操作?我已经尝试了降低会话超时(设置为一分钟),手动调用Abandon()以及手动调用GC.Collect(),都无济于事。
我们可以在此步骤捕获发生的错误以保护应用程序池吗?这里提出的例外记录w/Source = ASP.NET 2.0.50727.0并且没有到达global.asax中的应用程序错误处理程序。我们可以做什么来防范这种情况,即使经过适当的检查&余额应用于会话绑定对象?
任何见解,将不胜感激。
也许他们应该解决他们的代码不是允许serialziation异常崩溃的AppDomain。只是一个想法。 – 2010-06-30 04:53:20
这是一个很好的想法,我认为他们同意;这是一种极其罕见的情况,但应该防范。 – Nariman 2010-06-30 13:53:38
@John:看起来他正在使用Lucene.net。虽然这是一个第三方应用程序,据我所知,它的开源和他应当标注违规类'Serializable' – ram 2010-06-30 15:20:36