我们正在为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(),但都无济于事。
我们是否可以捕获此步骤中发生的错误以保护应用池?此处引发的异常将使用 Source = ASP.NET 2.0.50727.0 进行记录,并且不会访问global.asax中的应用程序错误处理程序。即使经过适当的检查后,我们还能做些什么来防范这种情况?余额是否应用于会话绑定对象?
任何见解都将不胜感激。
答案 0 :(得分:3)
我们能够在SOSS技术支持的帮助下解决这个问题 - 它们非常有用 - 以下是详细信息:
补救措施如下:
修复 System.Exception - 派生类型(可序列化但不可序列化);
删除Session_End Global.asax中的事件或禁用 到期事件( max_event_retries 在soss_params.txt中设置为0;
在这些情况下,很可能是 用户遇到一个 其中一个上的 SerializationException 他们的要求,意味着它到达 的的Application_Error 强>;在这里你可以清楚 会话密钥(必须清除所有 他们)或放弃会议 彻底;
订阅 AppDomain.UnhandledException 通知未处理的例外, 它们应该发生(这里没有追索权, 只记录);他们也可以 残疾人通过 legacyUnhandledExceptionPolicy (不是 推荐的);
答案 1 :(得分:1)
我们可以捕获此时发生的错误吗? 一步保护应用程序池?该 此处提出的异常记录为w / Source = ASP.NET 2.0.50727.0并没有 到达应用程序错误处理程序 在global.asax中。我们能做些什么? 甚至可以防范这种情况 经过适当的检查和结余 应用于会话绑定对象?
我不知道this是否可行,但你可以试一试
答案 2 :(得分:0)
我通过简单地完全删除SessionEnd方法来解决这个问题。当Asp.net使用反射搜索方法的存在然后运行有问题的代码时,删除方法的内容是不够的。