Сеансы и состояния

Лекция 13. Основные концепции проектирования корпоративных приложений (продолжение)

В процессе сеанса работы пользователя с системой возникают различные промежуточные данные актуальные для конкретного сеанса. Существуют подходы для организации работы как с состояниями так и без (Stateless Session и Stateful Session).

 

Сеанс без состояния (Stateless Session) предполагает отсутствия какой либо информации или предыстории взаимодействия в рамках сеанса для обслуживания запросов пользователя. В таком случае сеанс взаимодействия с системой может вырождаться до одного запроса. (Например обращение к поисковой системе).

 

Сеанс с состоянием (Stateful Session) предполагает наличие некоторой промежуточной информации в процессе общения пользователя с системой в рамках сеанса, при этом информация необходима для выполнения запросов в правильной последовательности. (Пример – корзина в электронном магазине).

 

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

 

К преимуществам сеанса без состояния следует отнести:

  • Высокая прозрачность запросов. Клиент передаёт серверу каждый раз всю необходимую информацию для выполнения запроса. Перехватив такой запрос и записав его в журнал (log file) технический специалист или средства автоматизированного контроля могут анализировать и проверять как правильность самомго отдельно взятого запроса, так и правильность ответа на него, так как отсутствие состояния часто предполагает тот факт что ответ на один и тот же запрос (т.е. запрос с одинаковыми параметрами) будет одинаковым. Таким образом запрос вырождается в функцию, на вход которой передаётся какая то информация (параметры запроса) а на выходе получается значение (ответ сервера). Если удаётся свести взаимодействие к такой модели, то тестирование, отладка и верификация резко упрощаются.
  • Относительно простая возможность наращивания производительности. Так как каждый последующий запрос не зависит от состояния и предыстории ни на каком сервере, то простое добавление серверов (горизонтальная масштабируемость) осуществляется относительно просто.
  • Упрощается возможность кеширования результатов запроса. Так как запросы не имеют никакой предыстории – то можно кешировать запрос, используя парамтры запроса в качестве ключа три.
  • Улучшается масштабируемость по количеству пользователей. Так как для большого количества сеансов нет необходимости хранить промежуточные состояния и результаты – не используются дополнительные ресурсы сервера (в первую очередь оперативная память), что крайне благотворно сказывается на максимальном количестве пользователей, которые сервер может обрабатывать с приемлимой производительностью.

 

К преимуществам сеанса с состоянием относятся:

  • Относительно низкий сетевой трафик. Так как сервер не передаёт никакую дополнительную и промежуточную информацию на клиент (за исключением быть может ключа самой сессии (в Java это как правило hidden поле jsessionid)).
  • Высокая конфиденциальность. Так как сервер не передаёт никакой информации вовне – снижается вероятность того, что эта информация может быть перехвачена и/или изменена. В случае сеанса с состоянием можно использовать шифрование данных передаваемых таким образом, однако это ещё больше увеличивает их объем, а так же может замедлить работу. Кроме того, данные всё равно могут быть легко перехвачены и впоследствии расшифрованы, а самое главное то, что в таком случае теряется такой важный плюс как прозрачность запрос-ответа, ибо зашифрованные данные уже никак нельзя назвать прозрачными. Шифрация же на каком либо общем ключе, который может использоваться третьей стороной (например сетевым монитором, который следит и регилирует за сетью) неприемлима, так как тут же встаёт проблема распределения ключей.
  • Относительная независимость от клиента. Сервер не пересылает информацию на клиент и, как следствие, он не ждёт, что клиент перешлёт ему эту информацию в правильном формате, правильной версии и т.п. Например при смене версии сервера, может потребоваться обновлять клиентов (хорошей новостью является то, что в случае токних Web-клиентов – это происходит прозрачно, так как клиент не содержит никакой логики за исключением того что возвращает то что было передано ему в hidden поле).

 

Недостатками каждого из подходов являются достоинства противоположного метода. Какому из них отдавать предпочтение – зависит от конкретной ситуации, и, быть может, от пожжержки со стороны технологической платформы.Так например обе платформы и Java 2 Enterprise Edition (J2EE) и .Net поддерживают HttpSession – вариант взаимодействия с состоянием. Использовать сессию очень просто и удобно, однако, при необходимости распределять приложение (например для балансировки нагрузки или кластеризации), необходимо соблюдать ряд мер, пренебрегание которыми способно в худшем случае вообще привести к невозможности запуска приложения на кластере или даже снизить производительность (например из-за интенсивной репликации сессии между узлами кластера). трибутыным решением здесь может быть применение так называемого подхода Session Affinity, т.е. гарантированная обработка запросов от одного клиента одним узлом кластера, что избавляет от необходимости постоянной репликации сессии (которая при неграмотном или неприспособленном проектировании может вообще оказаться не подлежащей репликации (non serializable)), однако не избавляет от проблемы повышения отказоустойчивости, так как в случае выхода из строя одного узла кластера, сессии, не будучи реплицированными на другие узлы – теряются.

Что касается использование подхода без состояния – то ASP.Net позволяет использовать мехинизм, называемый ViewState. Фактически – это аналог сессии, однако не хранимый на сервере, а передаваемый каждый раз на клиент в виде Base64 закодированного hidden поля. Положительным моментом тут является то, что сервер избавляет себя от дополнительной нагрузки связанной с репликацией и поддержкой трибу. Однако, резко отрицательным моментом оказывается то, что при неграмотном проектировании размер request-response может оказываться очень значительным (например около 1Мб, что сильно тормозит сетевое взаимодействие). Оданко, такой подход всё равно нельзя назвать подходом без состояния, так как значения ViewState им как раз и являются. А дополнительное кодирование по закрытому протоколу никак не прибавляет прозрачности взаимодействия.

 

 

Существует ряд подходов для сохранения состояния сеанса:

  • На стороне клинета (Client Session State). Предусматривает сохранение информации о состоянии сеанса на клиентской машине. Существуют следующие варианты:
    • Cookies
    • Hidden fields
    • Толстый клиент (rich client)
  • На стороне сервера (Server Session State). Сохраняет состояние сеанса на стороне сервера. Информация может размещаться:
    • В памяти;
    • В файловой системе сервера;
    • В базе данных.