Как защитить пулы приложений от исключений сериализации сессии?

Мы используем Поставщика Сессии Из процесса (ScaleOut) для приложения ASP.NET, и мы заметили, что то, когда объект это не правильно установка для десериализации непреднамеренно, превращает ее путь в сессию, которую это в конечном счете заставит весь процесс завершать.

Репродуцирование и обработка этого сценария состоят в том, где это становится еще более интересным.

Исключение, которое завершает процесс, повышено в 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. Что мы можем сделать для принятия мер против этого сценария, даже после соответствующих проверок, и балансы применяются к ограниченным сессией объектам?

Любое понимание ценилось бы.

7
задан Nariman 21 June 2010 в 17:09
поделиться

2 ответа

Мы смогли решить эту проблему с помощью технической поддержки SOSS - они очень помогли - вот детали:

  • По истечении срока действия сессии, SOSS поднимает событие истечения срока действия в своих клиентских библиотеках, которые в свою очередь отвечают за срабатывание Session_End в Global. asax (N.B: ScaleOut балансирует нагрузку между клиентами, поэтому веб-сервер, создавший сессию, может не обязательно получить событие истечения - это очень важно для воспроизведения этих проблем).
  • Поскольку это происходит вне контекста запроса, исключение не обрабатывается и убивает пул приложений;
  • Это крайне редкий сценарий, но, тем не менее, он будет рассмотрен в ближайших обновлениях;
  • Устранение проблемы заключается в следующем:

    1. Исправьте System.Exception-производный тип (сериализуемый, но не несериализуемый);

    2. Удалите события Session_End события в Global.asax или отключить события истечения срока действия (max_event_retries установить значение 0 в soss_params.txt);

    3. В этих сценариях, вероятно, что пользователь столкнется с SerializationException на одном из своих запросов, что означает, что он достигает Application_Error; здесь вы можете очистить ключи сессии (необходимо очистить все их) или отказаться от сессии полностью;

    4. Подписаться на AppDomain.UnhandledException, чтобы быть уведомление о необработанных исключениях, если они возникнут (здесь нет никаких средств защиты, только протоколирование); их также можно отключить через legacyUnhandledExceptionPolicy (not recommended);

3
ответ дан 7 December 2019 в 14:29
поделиться

Можем ли мы перехватить ошибки, возникающие в этом месте? шаг для защиты пула приложений? В исключения, возникающие здесь, регистрируются с Источник = ASP.NET 2.0.50727.0, а не добраться до обработчиков ошибок приложения в global.asax.Что мы можем сделать с остерегайтесь этого сценария, даже после соответствующих проверок и противовесов применяются к объектам, привязанным к сеансу?

Я не знаю, это будет работать, но вы можете попробовать

1
ответ дан 7 December 2019 в 14:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: