如何保护应用程序池免受会话序列化异常的影响?

我们为ASP.NET应用程序使用Out-of-Process会话提供程序( 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中的应用程序错误处理程序。 即使在对会话绑定对象应用适当的检查和平衡之后,我们可以做什么来防范这种情况?

  • 任何见解,将不胜感激。


    我们能够在SOSS技术支持的帮助下解决这个问题 - 他们非常有帮助 - 这里是详细信息:

  • 会话过期后,SOSS在其客户端库中引发过期事件,后者又负责在Global.asax中触发Session_End( 注意: ScaleOut负载均衡客户端之间的过期事件,因此创建会话的Web服务器可能不会收到到期事件 - 这对于试图重现这些问题至关重要)。
  • 由于这发生在请求的上下文之外,因此该异常未处理并终止应用程序池;
  • 这是一种非常罕见的情况,但他们仍然会在即将到来的维护版本中解决这个问题;
  • 补救措施如下:

  • 修复System.Exception -派生类型(可序列化但不可序列化);

  • 删除Global.asax中的Session_End事件或禁用过期事件( soss_params.txt中的max_event_retries设置为0);

  • 在这些场景中,用户可能在其某个请求中遇到SerializationException ,这意味着它会到达Application_Error ; 在这里您可以清除会话密钥(必须清除所有会话密钥)或直接放弃会话;

  • 订阅AppDomain.UnhandledException以通知未处理的异常,如果它们发生(这里没有追索权,只是记录); 它们也可以通过legacyUnhandledExceptionPolicy (不推荐)来禁用;


  • 我们是否可以捕获在此步骤发生的保护应用程序池的错误? 这里提出的例外记录w / Source = ASP.NET 2.0.50727.0,并没有达到global.asax中的应用程序错误处理程序。 即使在对会话绑定对象应用适当的检查和平衡之后,我们可以做什么来防范这种情况?

    我不知道这是否会奏效,但你可以尝试一下


    我通过完全删除SessionEnd方法来解决这个问题。 仅当Asp.net使用反射搜索方法的存在,然后运行有问题的代码时,删除方法的内容是不够的。

    链接地址: http://www.djcxy.com/p/46389.html

    上一篇: How to protect application pools from session serialization exceptions?

    下一篇: Implementing a filtering class loader