Замена сессии ASP.Net полностью - PullRequest
45 голосов
/ 24 января 2012

Сеанс ASP.Net кажется идеальным для традиционного приложения WebForms, но он делает некоторые вещи, которые представляют серьезную проблему для современного приложения AJAX и MVC.

В частности, есть только 3 способа доступа к ASP.Сетевой провайдер:

  1. Блокировка чтения и записи (по умолчанию) - сеанс заблокирован с AcquireRequestState срабатыванием до ReleaseRequestState срабатывания.Если из браузера одновременно поступают 3 запроса, они помещаются в очередь на сервере.Это единственная опция в MVC 2, но MVC 3 позволяет ...

  2. Без блокировки только для чтения - сеанс не заблокирован, но может 'быть сохраненным в.Похоже, что ненадежно, хотя , поскольку некоторые операции чтения снова блокируют сеанс.

  3. Сеанс отключен - любая попытка чтения или записик сеансу выдает исключение.

Однако с современным приложением MVC у меня происходит много событий AJAX одновременно - я не хочу, чтобы они были на сервере, но я хочуих можно записать в сеанс.

Мне нужен четвертый режим: Грязное чтение, последняя запись выигрывает

Я думаю (рад, что меня поправили)что единственный способ сделать это - полностью заменить сессии ASP.Net.Я могу написать своего собственного провайдера , но ASP по-прежнему будет вызывать его с одним из 3 поддерживаемых шаблонов.Есть ли способ заставить ASP.Net поддерживать оптимистичный параллелизм?

Это оставляет мне замену всех вызовов сеанса новым классом, который в основном делает то же самое, но не блокирует - что является болью.

Я хочу сохранить как можно больше информации о текущем сеансе (наиболее значительно идентификаторы сеансов в различных журналах) с минимальным количеством замены кода.Есть какой-либо способ сделать это?В идеале я бы хотел, чтобы HttpContext.Current.Session указывал на мой новый класс, но без блокировки ASP.Net каких-либо запросов.

Кто-нибудь уже сделал что-то подобное?Кажется странным, что со всеми приложениями AJAXey MVC это новая проблема с ASP.

1 Ответ

11 голосов
/ 26 января 2012

Прежде всего я говорю, что MS asp.net имеет блокировку в ядре сеанса asp.net, обрабатывающего страницу, где-то в dll webengine4.dll для asp.net 4

И я говорю это с точки зрения MS asp.net act correct and lock the session this way, поскольку asp.net не может знать, какую информацию мы храним на сеансе, поэтому может сделать правильные «последние записи побед».

Также корректно является блокировка для сеанса полная страница , потому что этот способ дает вам очень важную синхронизацию вашей программы, и по опыту теперь я говорю, что она вам нужна для большинства ваших действий. После того, как я заменил сеанс ms своим, на всех моих действиях мне нужно сделать глобальную блокировку, иначе у меня возникнут проблемы с двойными вставками, двойными действиями и т. Д.

Я даю пример проблемы, которую я здесь узнаю. Данные сеанса сохраняются в SessionSateItemCollection, который представляет собой список ключей. Когда сеанс читает или пишет эту коллекцию, делайте все это вместе. Итак, давайте посмотрим на это дело.

у нас есть дерево переменных в сеансе, "VAR1", "VAR2", "VAR3"

Стр. 1.
getsession (фактически получить все данные и поместить их в список)
сеанс [VAR1] = "данные1";
savesession ()
результат VAR1 = data1, VAR2 = (последние данные var2), VAR3 = (последние данные var3)

Страница 2.
getsession (фактически получить все данные и поместить их в список)
сеанс [VAR2] = "data2";
savesession ()
результат VAR1 = (последние данные var1), VAR2 = data2, VAR3 = (последние данные var3)

Страница 3.
getsession (фактически получить все данные и поместить их в список)
сеанс [VAR3] = "data3";
savesession ()
результат VAR1 = (последние данные var1), VAR2 = (последние данные var2) VAR3 = "data3"

Обратите внимание, что на каждой странице есть клон данных, поскольку он считывал их с носителя сеанса (например, когда они последний раз читали из базы данных)

Если мы позволим этим 3 страницам работать без блокировки, у нас фактически не будет грязного чтения, нет "последней записи, которая выигрывает" - здесь мы имеем " последняя запись уничтожает другие ", потому что если вы снова об этом думаете, когда VAR1 меняются, почему VAR2 и VAR3 остаются прежними? Что делать, если у вас есть изменить VAR2 где-то еще.

и по этой причине мы не можем оставить это без блокировки как есть.

А теперь представьте себе, что с 20 переменными ... совершенно беспорядок.

Возможные решения

Из-за многопоточности asp.net для многих пулов единственный способ сохранить одни и те же данные в разных пулах и на разных компьютерах - это иметь общую базу данных или общую для всех процессов программу, такую ​​как служба состояний asp.net. ,

Я предпочитаю иметь общую базу данных проще, чем создавать программу для этого предложения.

Теперь, если мы подключим файл cookie , который мы создаем, к пользователю с пользователем данных сеанса , и мы будем управлять данными, используя полностью настраиваемое поле базы данных, которое нам известно что нам нравится блокировать, что нет, как сохранять или изменять или сравнивать и сохранять данные последних записей о выигрышах, мы можем выполнить эту работу и полностью отключить сеанс asp.net, который является общим хранителем сеансов, созданным для всех нужд, но не для обработки особых случаев, подобных этому.

Может ли asp.net сделать эту работу в будущем выпуске, да, он может сделать дополнительное поле, называемое грязным, и в сеансе сохранить данные, выполнить слияние данных, используя грязное поле, или что-то подобное, но может не заставляйте это сейчас работать как есть - по крайней мере из того, что я нашел до сих пор.
На самом деле SessionStateItem имеет грязный флаг для свойств, но не произвел это слияние в конце сохранения данных. Я действительно буду любить, если кто-то еще найдет решение для существующего хранителя состояния сеанса ms asp.net, я напишу то, что нашел до сих пор, но это не значит, что точно нет пути - я не нашел как есть.

Надеюсь, что все поможет:)

Пользовательский SessionStateModule

в этом ответе https://stackoverflow.com/a/3660837/159270 Джеймс после записи пользовательского модуля говорит: Я все еще не могу поверить, что пользовательская реализация ASP.Net Session блокирует сеанс для всего запроса.

...