對於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(),都無濟於事。
我們可以在此步驟捕獲發生的錯誤以保護應用程序池嗎?這裏提出的例外記錄w/Source = ASP.NET 2.0.50727.0並且沒有到達global.asax中的應用程序錯誤處理程序。我們可以做什麼來防範這種情況,即使經過適當的檢查&餘額應用於會話綁定對象?
任何見解,將不勝感激。
也許他們應該解決他們的代碼不是允許serialziation異常崩潰的AppDomain。只是一個想法。 – 2010-06-30 04:53:20
這是一個很好的想法,我認爲他們同意;這是一種極其罕見的情況,但應該防範。 – Nariman 2010-06-30 13:53:38
@John:看起來他正在使用Lucene.net。雖然這是一個第三方應用程序,據我所知,它的開源和他應當標註違規類'Serializable' – ram 2010-06-30 15:20:36