Как работает механизм состояния сеанса в ASP.NET
Что проверяют
Понимаете ли вы, где на самом деле лежат данные сеанса, как запрос их находит и что будет при нескольких серверах. Следом обычно спрашивают, чем сеанс отличается от аутентификационной cookie и почему в него нельзя складывать всё подряд.
Как отвечать
Общая схема одна: сервер выдаёт клиенту cookie с идентификатором, а данные хранит у себя по этому ключу. Дальше важно разделить две платформы.
В классическом ASP.NET на System.Web сеанс включён по умолчанию, cookie называется ASP.NET_SessionId, режим задаётся в web.config: InProc (память процесса), StateServer, SQLServer или свой провайдер. Тайм-аут скользящий, 20 минут. Важная деталь: запросы одного сеанса сериализуются блокировкой, поэтому параллельные AJAX-запросы идут друг за другом, если не выставить ReadOnly.
В ASP.NET Core сеанс нужно подключить явно:
- хранилище:
IDistributedCache, напримерAddDistributedMemoryCache()для одного экземпляра или Redis черезAddStackExchangeRedisCache()для фермы; - настройка:
AddSession(o => ...)сIdleTimeout(по умолчанию 20 минут),Cookie.HttpOnlyиCookie.IsEssential; - конвейер:
app.UseSession()послеUseRoutingи до маппинга контроллеров; - доступ:
HttpContext.Session.SetString,GetInt32и прочие. Хранятся только байты, объекты сериализуют в JSON сами.
Cookie .AspNetCore.Session защищена через Data Protection, поэтому в ферме серверам нужен общий набор ключей, а не только общий Redis. Блокировок в Core нет: при параллельных запросах выигрывает последняя запись.
Где спотыкаются
Держат сеанс в памяти процесса и масштабируют приложение на несколько экземпляров. Без липких сессий пользователь теряет данные на части запросов, а при перезапуске их теряют все.
Кладут в сеанс крупные объекты и целые сущности. Каждый запрос тянет их из хранилища и пишет обратно, сеанс становится узким местом.
Используют сеанс вместо аутентификации и хранят в нём признак «вошёл». Для входа есть cookie-аутентификация, а сеанс живёт по своему тайм-ауту и может исчезнуть раньше.