2010-06-21 23 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使用反射搜索方法的存在,然後運行有問題的代碼時,刪除方法的內容是不夠的。

相關問題