Почему/когда сеансовая запись уязвима для завершения потока?

КОД:

Session["foo"] = "bar";  
Response.Redirect("foo.aspx");

ПРОБЛЕМА:

Когда foo.aspx читает "foo" из сеанса, он не существует. Сеанс есть, но нет значения для "foo".

Я наблюдал это с перерывами в нашей производственной среде. Но я не хочу здесь задавать вопрос о Response.Redirect().

ОБЪЯСНЕНИЕ:

Бертран Ле Рой объясняет (смелый мой):

Теперь, что делает Redirect, является отправка специальный заголовок для клиента, чтобы он запрашивает сервер для другого чем тот, который он ожидал. На стороне сервера, после отправки заголовок, Перенаправление завершает ответ. Это очень жестокая вещь.Response.End фактически останавливает выполнение страницы, где бы она ни находилась используя исключение ThreadAbortException. Какие действительно, здесь происходит то, что токен сеанса теряется в битве.

Мой вынос - это то, что Response.Redirect() может быть тяжелым с конечными потоками. И это может угрожать моей сессии, если они слишком близки к этой тяжелой работе.

ВОПРОС:

Как насчет управления сеансом ASP.NET делает его настолько уязвимым для этого? Строка ответа Response.Redirect() не начинает свое выполнение до тех пор, пока строка записи сеанса не будет завершена - как это может быть такой угрозой для моего сеанса записи?

Как насчет записи сеанса не заканчивается до того, как выполняется следующая строка кода? Существуют ли другие сценарии, в которых записи сеанса аналогично (как будто они никогда не возникали) теряются?

+5
источник поделиться
3 ответа

После тестирования нескольких альтернатив (Response.Redirect(..., false), Server.Transfer() и других "решений", которые я теперь не могу вспомнить), мы нашли только один надежный ответ на эту проблему.

Перемещение состояния сеанса из InProc в SqlServer эффективно устранило это поведение из наших систем, оставив Response.Redirect(...) полностью надежным. Если дальнейшее тестирование будет показано иначе, я сообщу здесь, но я говорю, чтобы эта остановка происходила в вашей среде: переместите состояние сеанса в SqlServer (или "из InProc" достаточно хорошо? Я не уверен).

+1
источник

Я не достаточно хорошо знаком с внутренними функциями написания сеанса, но я думаю, что он имеет некоторые сложности, поскольку он полагается на перевод файлов cookie сеанса браузера в идентификацию сервера. Кроме того, ThreadAbortExceptions имеют особые соображения во время выполнения, которые могут играть здесь, я не уверен.

В любом случае Response.Redirect() имеет перегрузку, которая принимает логический параметр, который позволяет указать, хотите ли вы закончить поток или нет.

Response.Redirect(string url,  bool endResponse);

Если вы вызываете его с параметром endResponse, установленным на "false", он будет изящно завершен, вместо того, чтобы называть Thread.Abort() внутренне. Однако это означает, что он также выполнит любой код, оставшийся в жизненном цикле страницы, до завершения.

Хорошим компромиссом является вызов Response.Redirect(url, false), за которым следует Application.CompleteRequest(). Это позволит осуществить перенаправление, но также изящно отключит текущий контекст выполнения с минимальным количеством дополнительной обработки жизненного цикла.

+2
источник

Перезапуск пула приложений может привести к тому, что ваш сеанс исчезнет. Вы можете настроить пул приложений на повторное использование в определенное время (рекомендуется, а также в ночное время или в периоды низкого использования) или увеличить период ожидания вашего пула приложений.

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос