代码之家  ›  专栏  ›  技术社区  ›  Nariman

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

  •  7
  • Nariman  · 技术社区  · 15 年前

    我们正在使用进程外会话提供程序( 标出 )对于ASP.NET应用程序,我们注意到 什么时候? 未正确设置反序列化的对象无意中进入了它将要执行的会话。 最终导致整个过程终止 .

    复制和处理这个场景会变得更加有趣。

    在中引发终止进程的异常 会话状态中的任何状态对象 其实现非常简单:

    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)
    

    我们想了解两件事:

    1. 什么时候 燃烧结束 为一个进程外的提供者开火,更重要的是,我们如何在一个没有负载的开发环境中模拟这一点?我尝试过降低会话超时(设置为一分钟)、手动调用放弃()和手动调用gc.collect(),所有这些都无效。

    2. 我们是否可以捕获在此步骤中发生的错误以保护应用程序池?此处引发的异常记录为w/ 源=ASP.NET 2.0.50727.0 不要访问global.asax中的应用程序错误处理程序。即使在将适当的检查和平衡应用于会话绑定的对象之后,我们还能做些什么来防止这种情况发生?

    任何见解都会受到赞赏。

    3 回复  |  直到 9 年前
        1
  •  3
  •   Nariman    15 年前

    我们在SoSS技术支持的帮助下解决了这个问题,这些技术支持非常有用,具体如下:

    • 会话到期时,SOSS在其客户机库中引发一个到期事件,而该事件又负责在global.asax中触发会话\end。( N. B: scaleOut负载在客户端之间平衡过期事件,因此创建会话的Web服务器可能不需要接收其过期事件-这对于尝试重现这些问题至关重要)。
    • 因为这发生在请求的上下文之外,所以异常是未处理的,并且会终止应用程序池;
    • 这是一个非常罕见的场景,但他们仍将在即将发布的维护版本中解决这一问题;
    • 补救措施如下:

      1. 修复 系统异常 -派生类型(可序列化但不可不可序列化);

      2. 删除会话结束 global.asax中的事件或禁用 过期事件( 最大事件重试次数 在soss_params.txt中设置为0);

      3. 在这些情况下,很可能 用户遇到 序列化异常 在其中之一 他们的要求,意味着达到 应用程序错误 ;在这里你可以清理 会话密钥(必须清除所有 或者放弃会议 彻底的;

      4. 订阅 AppDomain.UnhandledException 成为 通知未处理的异常, 如果发生(这里没有追索权, 只是伐木);它们也可以 残疾人通过 法律处理例外政策 (不是) 建议);

        2
  •  1
  •   ram    15 年前

    我们能捕捉在这发生的错误吗 要保护应用程序池吗?这个 此处引发的异常记录为/ 源=ASP.NET 2.0.50727.0,不 到达应用程序错误处理程序 在global.asax中。我们能做什么 即使在这种情况下也要小心 在适当的检查和平衡之后 是否应用于会话绑定对象?

    我不知道是否 this 会有用的,但你可以试试看

        3
  •  0
  •   Karlth    9 年前

    我只需完全删除sessionend方法就可以解决这个问题。当ASP.NET使用反射搜索方法的存在,然后运行有问题的代码时,删除方法的内容是不够的。

    推荐文章