Страницы

Поиск по вопросам

среда, 4 декабря 2019 г.

Использование механизма сессий для хранения временных данных

#aspnet #aspnet_mvc


В разрабатываемом приложении осуществляется тестирование пользователей. Естественно
во время теста возникла необходимость сохранять промежуточные итоги: Количество ошибок,
количество правильных ответов и пр. В начале планировалось проводить тест почти полностью
на клиенте, но потом возникли сложности с тем чтобы защититься от подделки данных и
решено было перенести все на сервер. Теперь возник вопрос:
Разумно ли и безопасно хранить текущие данные в сессии или лучше добавлять их в БД?
    


Ответы

Ответ 1



Безопасно. Сессия полностью хранится на серверной стороне. Но вот разумно ли - зависит от мнения. Мое мнение: НИ В КОЕМ СЛУЧАЕ НЕ ИСПОЛЬЗУЙТЕ СТАНДАРТНЫЙ МЕХАНИЗМ СЕССИЙ В ASP.NET ...и опирающийся на него же механизм TempData. Практически ни к коем случае, кроме редких исключений, описанных в конце ответа. Несмотря на всю простоту использования, у механизма сессий есть огромное количество потенциальных проблем. Проблемы из-за самого наличия сессионной куки Запросы с общей сессионной кукой всегда выполняются последовательно. ASP.NET тупо не может выполнить два запроса из одной сессии одновременно. Он ставит их в очередь и вызывает по одному. Это дико бьет по производительности. Если пользователь запустил что-то долгое (репорт на минуту) на сайте в одном табе - то в другом табе сайт у него тупо будет висеть. Это написано мелким шрифтом в MSDN на странице, посвященной сессиям, но кто ж читает MSDN. Это частично решается явным отключением сессии для всех страниц и всех контроллеров по умолчанию, и выборочным включением ее для отдельных действий, в случае необходимости. Проблемы со стандартным способом хранения - InProc: Стандартный механизм хранения сессий ненадежен. Он будет терять данные при ресайкле приложения - при неактивности, при большой нагрузке, при заливке новой версии. Стандартный механизм хранения сессий не масштабируется. Он просто не работает в случае двух серверов. Или одного сервера и двух рабочих процессов. Или одного сервера, одного рабочего процесса при включенном Overlapping Recycling. Проблемы с хранением сессии в SQL Server: В зависимости от объема хранимых данных - это может быть медленно. SQL Server не приспособлен к хранению больших объемов данных прямо в таблице. Он делает это меееедлееенно. Проблема "в один момент времени - один запрос" при этом выходит на новый уровень. Теперь каждый запрос, использующий сессию, ставит на нее блокировку. Вызовом SQL. А потом снимает ее. Вызовом SQL. Что дает вам два запроса к базе на ровном месте, даже если контроллер не лезет в сессию. В зависимости от провайдера, можно напороться еще и на проблему в очисткой сессий, например, рекомендованные (с) System.Web.Providers (r), при обработке каждого запроса лезут в базу еще и для того, чтобы почистить старые сессии. Каждого запроса, Карл! Что использовать вместо сессий В живом - открытом в интернет, или просто доступном большому количеству пользователей приложении альтернатив в смысле "правильных замен сессии" нет. Сама по себе необходимость организовать что-то вроде сессии - это прямой и однозначный признак просчета в архитектуре. Использование сессий или любого их подобия практически означает невозможность распределенного деплоя. Убирает возможность эффективно использовать кэш. Сессии - это всегда bottleneck. Если они нужны - значит вы делаете что-то неправильно. Например, в случае с приложением для тестирования стоит хранить на клиенте данные ответы. Это не исключает хранения промежуточных итогов, но окончательный итог надо подсчитывать на сервере, и только с использованием самих ответов, а не промежуточных итогов. Промежуточные итоги можно использовать для валидации - если вдруг что-то разошлось - значит клиент пытался читерить. С другой стороны если у вас intranet-приложение, которым пользуются, например, студенты, при прохождении теста, то одного сервера с одним рабочим процессом и настроенным хранением сессии в ASP.NET State Server вам хватит заглаза. От вас потребуется только поставить стандартный сервер через вызовом aspnet_state.exe, прописать режим StateServer в конфиге и отметить все хранимые объекты как сериализуемые. Это в разы проще, чем ручная организация хранения сложных временных объектов в базе. Только режим хранения InProc не используйте - он не предназначен для использования в хоть насколько-то рабочем окружении.

Комментариев нет:

Отправить комментарий