Почему делает мой огонь приложения MVC ASP.NET Session_Start многократно для единственной сессии?

У нас есть приложение MVC.NET, которое встречается с фатальными ошибками, когда оно перезапускает. В нашем обработчике событий Session_Start мы добавляем идентификатор сессии к словарю. В обработчике Session_End мы удаляем его. Рассмотрите следующую последовательность запросов:

ПОЛУЧИТЕ home.mvc
<перезапуски приложения>
ПОЛУЧИТЕ main.css
ПОЛУЧИТЕ banner.jpg
ПОЛУЧИТЕ somedata.mvc
...

Из-за пути проектируется приложение, этот вид последовательности происходит справедливо часто, если Вы делаете восстанавливание, в то время как приложение открыто в окне браузера. Это ужасно не коснулось бы за исключением того, что я вижу его в продуктивных средах также. Например, это произойдет (хотя редко) при редактировании web.config.

Запросы после перезапуска происходят все из-за ссылок в домашней странице или вызовах Ajax от JavaScript.

То, что я наблюдаю, - то, что.NET обрабатывает первые 5 запросов параллельно. Каждый такой запрос заставляет это запускать событие Session_Start. После короткого времени это запускает времена события 3 Session_End. Чтобы быть ясным, каждый Session_Start соответствует той же самой сессии. У них всех есть тот же идентификатор сессии, и свойство IsNewSession верно для всех объектов состояния сеанса. Кроме того, события Session_End не соответствуют уничтожаемой сессии. Сессия сохраняется, наряду с любыми данными, хранившими в состоянии сеанса.

Я должен или препятствовать тому, чтобы он запустил Session_Start несколько раз, или выяснить, как сказать, когда Session_End действительно не означает, что сессия закончилась.

8
задан Peter Ruderman 19 November 2018 в 17:14
поделиться

2 ответа

Ответ на этот вопрос оказался довольно прямым, хотя поведение определенно сбивало с толку.

Обычно MVC синхронизирует все запросы к приложению с помощью блокировки состояния сеанса приложения (поскольку http-модуль MVC отмечен как требующий состояния сеанса). В моем сценарии приложение перезапускается после обслуживания главной страницы. Таким образом, когда приходят запросы, относящиеся к основной странице, для этого идентификатора сеанса еще нет состояния сеанса, и запросы выполняются параллельно.

Я вижу 5 параллельных запросов, потому что я разрабатываю для XP, а настольные версии IIS ограничены 5 параллельными запросами. Поскольку объект состояния сеанса не существует ни для одного из этих запросов, каждый запрос создает новый объект состояния сеанса и запускает Session_Start. Четыре запроса относятся к методам действий MVC. Поскольку для этого требуется состояние сеанса, .NET пытается синхронизировать созданные объекты состояния сеанса с резервным хранилищем после завершения запросов.

Успешной может быть только первая синхронизация. .NET просто отбрасывает три дополнительных объекта состояния сеанса и запускает Session_End для каждого из них. .NET не пытается синхронизировать пятый объект состояния сеанса с резервным хранилищем, поскольку он был создан для асинхронного модуля http, который помечен как требующий состояния сеанса только для чтения.

Итак, исправление состоит из двух частей:

(1) В моем обработчике Session_Start я теперь проверяю, доступен ли объект состояния сеанса только для чтения. Если да, то я немедленно возвращаюсь, ничего не делая. .NET не будет запускать соответствующий Session_End, и поэтому все, что я делаю, в любом случае не будет очищено должным образом.

(2) Теперь я веду счетчик ссылок в моем словаре. Я увеличиваю счетчик каждый раз, когда обработчик Session_Start пытается добавить идентификатор сеанса, и уменьшаю его каждый раз, когда Session_End пытается его удалить. Когда счетчик достигает 0, я удаляю идентификатор сеанса из своего словаря.

3
ответ дан 6 December 2019 в 00:04
поделиться

Идентификатор сессии можно использовать повторно, если клиент посылает вам значение, срок действия которого истек. Прочитайте об атрибуте regenerateExpiredSessionId элемента здесь и обратите внимание, что значение по умолчанию - "true"

Вам также может быть интересно здесь:

1
ответ дан 6 December 2019 в 00:04
поделиться
Другие вопросы по тегам:

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