2010-06-21 34 views
7

对于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) 

我们想了解两件事:

  1. 何时FireSessionOnEnd为进程外提供程序启动,更重要的是,我们如何在没有负载的开发环境中模拟此操作?我已经尝试了降低会话超时(设置为一分钟),手动调用Abandon()以及手动调用GC.Collect(),都无济于事。

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

任何见解,将不胜感激。

+1

也许他们应该解决他们的代码不是允许serialziation异常崩溃的AppDomain。只是一个想法。 – 2010-06-30 04:53:20

+0

这是一个很好的想法,我认为他们同意;这是一种极其罕见的情况,但应该防范。 – Nariman 2010-06-30 13:53:38

+0

@John:看起来他正在使用Lucene.net。虽然这是一个第三方应用程序,据我所知,它的开源和他应当标注违规类'Serializable' – ram 2010-06-30 15:20:36

回答

3

我们能够解决这一问题的SOSS技术支持帮助 - 他们是极大的帮助的 - 这里有细节:

  • 在会话到期,SOSS引发期满事件在其客户端库,而这又是负责发射的Global.asax Session_End中(注:跨客户端 ScaleOut负载平衡失效事件,所以网络服务器那c重新召开会议可能不会收到其过期事件 - 这是试图重现这些问题的关键)。
  • 因为这种情况发生的请求的上下文之外,该异常是未处理的和杀死应用程序池;
  • 这是一个非常罕见的情况,但一个,他们将仍然在即将到来的维护版本解决;
  • 的补救措施如下:

    1. 修复System.Exception的衍生型(这是可序列化的但不是不可序列化的);

    2. 在Global.asax中删除Session_End中 事件或禁用 期满事件(max_event_retries 设置为0 soss_params.txt);

    3. 在这些情况下,它很可能是 用户遇到 SerializationException上 他们的要求之一,这意味着它达到 的Application_Error;在这里你可以清除 会话密钥(必须清除所有的 它们)或放弃会话 彻底;

    4. 订阅 AppDomain.UnhandledException是 通知未处理异常, 他们应该发生(在这里没有追索权, 只是记录);它们也可以通过 legacyUnhandledExceptionPolicy禁用(未 推荐);

1

我们可以捕获在此 步骤发生的错误来保护应用程序池吗? 在这里提出的例外记录w/ Source = ASP.NET 2.0.50727.0,而不是 达到global.asax中的应用程序错误处理程序 。我们能做些什么 警惕这种情况,即使 经过适当检查&余额 是否应用于会话绑定对象?

我不知道是否this会的工作,但你可以给它一个镜头

+0

谢谢,但这并没有真正防范这种情况,它只是让你记录它。以下是重现的一种快速方法:http://www.brianlow.com/index.php/2007/01/11/catching-unhandled-aspnet-exceptions/。后台线程*必须*捕获异常,或船舶停机。 – Nariman 2010-06-30 14:02:57

0

我通过简单地完全去除SESSIONEND方法固定于此。仅当Asp.net使用反射搜索方法的存在,然后运行有问题的代码时,删除方法的内容是不够的。

相关问题