Серия «Альтернативное мнение по продуктам WebSphere»: Назад к основам: Аварийное переключение сессии

Используете ли вы технологию HttpSession надлежащим образом? Java™ Servlet API предоставляет интерфейс HttpSession для отслеживания сессий и управления состоянием на протяжении нескольких запросов, что позволяет сервлетам связать определенного пользователя с серией его запросов. Однако если ваша база данных или ваша сеть демонстрирует плохую производительность, или сбор мусора на ваших серверах приложений происходит слишком часто, то, возможно, это означает, что вы используете HttpSession преимущественно в качестве кэша приложений. Из журнала IBM WebSphere Developer Technical Journal.

Том Элкотт, консультант по информационным технологиям, WSO2 Inc

Том Элкотт (Tom Alcott) работает консультантом по информационным технологиям в IBM, США. Том является членом группы по технической поддержке международных продаж продуктов WebSphere (Worldwide WebSphere Technical Sales Support) с момента ее основания в 1998 г. и в этом качестве большую часть рабочего времени тратит на повышение своего технического уровня по вопросам, интересующим потенциальных клиентов. До начала работы с WebSphere он был системным инженером в лаборатории IBM Transarc Lab , где занимался поддержкой программных продуктов TXSeries. Том имеет более чем 20-летний опыт проектирования и разработки приложений для мэйнфреймов и для распределенных систем. Он часто пишет и активно выступает на многие темы, связанные с исполнением продуктов WebSphere.



23.06.2009

В каждом выпуске серии The WebSphere Contrarian (Альтернативное мнение по продуктам WebSphere) автор отвечает на вопросы, дает рекомендации или другими способами обсуждает фундаментальные темы, связанные с использованием продуктов WebSphere. Достаточно часто в выпуске может предлагаться проверенный на практике совет, противоречащий преобладающей точке зрения.

Пришло время освежить ваши знания

На протяжении нескольких последних недель я потратил много времени на подготовку наших технических специалистов по поддержке продаж – я занимался с ними недавно выпущенной версией IBM® WebSphere® Application Server V7. Часть этой подготовки была посвящена проработке базового материала – для первичного обучения специалистов, плохо знакомых с продуктом WebSphere Application Server, и для обновления знаний специалистов, обладающих более серьезным опытом в этой области. Как оказалось, очень многие специалисты второй категории нашли проводимые мной лабораторные и лекционные занятия весьма полезными – и таких специалистов оказалось гораздо больше, чем я предполагал. И это правильно: никто не сможет стать настолько опытным, чтобы не нуждаться в периодическом возвращении к основам.

Находясь под впечатлением от этих занятий, я решил в этой статье рассмотреть один из важнейших аспектов функционирования продукта WebSphere Application Server, а именно: переключение сессии при отказе (session failover). Точнее, переключение сессии при отказе и мои рекомендации по этому поводу.


Почему именно HttpSession?

Hypertext Transfer Protocol (HTTP) – основной протокол для Web-приложений – относится к категории протоколов без запоминания состояния (stateless protocol (EN)). В общем случае, управление состоянием осуществляется с помощью cookie-файлов, которые отслеживаются браузером для сохранения состояния между запросами. Этот механизм позволяет связать серию уникальных запросов от определенного пользователя в своего рода «разговор» или поток. Однако управление состоянием с использованием cookie-файлов – это непростая задача. К счастью, сервлет Java Servlet API предоставляет средство для преодоления этого недостатка – интерфейс HttpSession, поддерживающий отслеживание сессии и управление ее состоянием на протяжении нескольких запросов посредством так называемого сессионного объекта (session object), что позволяет сервлетам связать определенного пользователя с серией его запросов.


HttpSession: когда и как

К сожалению, данные для определенной сессии могут быть сохранены в сессионных объектах. Я говорю «к сожалению», поскольку достаточно часто это приводит к использованию HttpSession в качестве кэша приложений, для чего эта технология на самом деле не была предназначена. В самом использовании сессии для связывания запросов от пользователя нет ничего предосудительного, однако использование сессии в качестве кэша приложений стимулирует увеличение числа методов разработки, способных «нагрузить» многие аспекты среды для исполнения приложений. Например, один из клиентов имел сессионные объекты размером 25 МБ (это не опечатка), персистентные по отношению к базе данных, что приводило к следующим результатам:

  • низкая производительность базы данных, поскольку ей приходилось выполнять сотни обновлений с (очень) большими сессионными объектами в своих таблицах;
  • снижение производительности сети в процессе «выталкивания» указанных обновлений из серверов приложений на сервер базы данных;
  • частые операции по сбору мусора для серверов приложений, поскольку ресурсы heap-области, которые в иной ситуации могли бы использоваться в интересах приложений, потреблялись сессионными объектами, связанными с каждым пользователем (например, 200 пользователей по 25 МБ – это 500 МБ (0,5 ГБ) только на сессионные объекты!). Даже heap-область размером 1 ГБ или 2 ГБ является слишком «маленькой» для хранения такого количества данных о состоянии приложения.

В свою очередь, такое несоответствующее использование HttpSession вынуждает беспокоиться о потере содержимого сессионного объекта, поскольку воссоздание хранящейся в нем информации отнимает много времени.

Как вы, возможно, уже догадались, я рекомендую не использовать HttpSession в качестве кэша приложений и, наоборот, использовать HttpSession для связывания нескольких запросов пользователя. Наилучший вариант – поддерживать минимально возможные размеры HttpSession. Однако разработчики некоторых приложений не прислушивались к этому совету, вследствие чего вам может потребоваться быстрый способ для изменения приложения с целью уменьшения его персистентности с минимальными последствиями. В этом случае я рекомендую использовать методику, изложенную в статье под названием Improving HttpSession Performance with Smart Serialization (EN) (Улучшение производительности HttpSession при помощи интеллектуальной сериализации), для сведения к минимуму того, что фактически хранится в сессионном объекте. В свою очередь, это минимизирует нагрузку на сервер приложений, если вы захотите использовать распределение сессии.


Распределение сессии: когда и как

Сервлет Servlet API создает условия для распределения сессионных объектов. Другими словами, вы можете использовать копии сессионных объектов таким образом, чтобы отказ какого-либо экземпляра сервера приложений не приводил к потере состояния приложения для определенного пользователя – точнее, для пользователей, поскольку весьма вероятно, что с данным экземпляром сервера приложения связано несколько пользователей (посредством механизма родственности HttpSession (affinity), предоставляемого продуктом WebSphere Application Server).

Я предпочитаю альтернативный вариант – вместо распределения сессии использовать подключаемый affinity-модуль HTTP-сервера для «прикрепления» пользователя к серверу приложений, хотя в случае остановки виртуальной машины (JVM) сервера приложений это приведет к потере HttpSession-объекта. Преимущество подобного подхода – отсутствие необходимости в распределении сессионных объектов с целью поддержки переключения объекта HttpSession на случай отказа или остановки сервера приложений. Очевидный недостаток этого подхода состоит в том, что в случае отказа/остановки пользователь теряет состояние любого приложения, в результате чего ему придется повторно входить в это приложение и воссоздавать указанное состояние. В некоторых случаях это может оказаться неприемлемым для вашего приложения или для ваших бизнес-требований. Я работал со многими клиентами, которые фактически согласились с моей точкой зрения и сделали ее своей стандартной практикой.

Возможно, вы действительно не можете допустить, чтобы кому-либо приходилось повторно входить в приложение и воссоздавать объект HttpSession «с нуля». Возможно, это происходит потому, что, к сожалению, вы решили использовать HttpSession в качестве кэша приложений, а возможно – по какой-либо другой причине. Так или иначе, продукт WebSphere Application Server Network Deployment (далее называемый Network Deployment) предоставляет два механизма для распределения сессии: сервис DRS (Distributed Replication Service) и механизм персистентности базы данных. Моя рекомендация по механизму распределения сессии Network Deployment остается неизменной (см. более раннюю статью (EN)): использовать персистентность базы данных.

Другая альтернатива для распределения сессии – использование продукта WebSphere eXtreme Scale, ранее известного в качестве ObjectGrid-компонента в составе продукта WebSphere Extended Deployment. Продукт WebSphere eXtreme Scale предоставляет основанный на использовании памяти механизм репликации, независимый от процесса исполнения сервера приложений. Это позволяет использовать продукт WebSphere eXtreme Scale для разделения состояния приложения (или кэша) между несколькими приложениями, исполняющимися на разных серверах приложений. Применительно к HttpSession, продукт WebSphere eXtreme Scale предоставляет фильтр сервлета, который подменяет собой HttpSession-реализацию для любого EAR-файла платформы Java EE (Java Platform, Enterprise Edition). Этот фильтр легко устанавливается в EAR с помощью сценария, предоставляемого продуктом WebSphere eXtreme Scale.

Следует отметить, что если вы действительно используете HttpSession в качестве кэша приложений, то, вероятно, WebSphere eXtreme Scale – это более предпочтительный вариант по сравнению с использованием средств Network Deployment для распределения сессии. Это объясняется тем обстоятельством, что продукт WebSphere eXtreme Scale изначально разрабатывался в качестве распределенного кэша приложений, тогда как интерфейс HttpSession никогда не предназначался для подобного использования. С другой стороны, если HttpSession используется эффективно, как описывалось выше, то средства Network Deployment для распределения сессий также демонстрируют эффективность и масштабируемость.


Совместное использование HttpSession

К решению о применении распределения сессии имеет отношение другое решение – о совместном использовании сессии ячейками Network Deployment. Моя рекомендация, которую я уже обсуждал прежде (EN), состоит в том, чтобы не поступать подобным образом. Это повышает сложность и создает взаимозависимости между вашими ячейками Network Deployment и, в более широком смысле, между вашими центрами обработки данных, а ведь именно этого вы хотите избежать в случае катастрофического события. Несмотря на то что, по всей видимости, многие клиенты согласны с этим тезисом, они все еще упорствуют в разделении сессии между ячейками центра обработки данных, поскольку не способны должным образом связать пользователя с сервером приложений в определенном центре обработки данных (или в ячейке).

К счастью, эта ситуация имеет решение, которое вы можете применить на сетевом уровне – при условии, что вы располагаете надлежащей инфраструктурой, а все затрагиваемые операционные сущности на вашем предприятии взаимодействуют надлежащим образом. Если вы создали несколько независимых ячеек (рисунок 1), то сможете сконфигурировать свой сетевой коммутатор (или глобальный селектор сайтов, как он часто называется) для корректной поддержки родственности данного пользователя к определенной ячейке.

Рисунок 1. Инфраструктура с несколькими независимыми ячейками
Рисунок 1. Инфраструктура с несколькими независимыми ячейками

Как реализовать такую конфигурацию? Большинство устройств этого типа применяют IP-механизмы 2-го или 3-го сетевого уровня для поддержания родственности клиента серверу; некоторые примеры таких механизмов: хеш IP-адресов, разрешение имен DNS и т.д. Эти типы механизмов родственности прекрасно работают до тех пор, пока весь входящий трафик при каждом запросе маршрутизируется единообразно и согласованно. Однако если трафик маршрутизируется через прокси-серверы или через другие посреднические устройства, которые в конечном итоге маскируют «реальный» IP-адрес клиента, подобных механизмов родственности недостаточно для того чтобы гарантировать непротиворечивую маршрутизацию запросов клиента к тем же самым серверам (или ячейкам).

К сожалению, такие методы маскировки или сокрытия применяются слишком часто; иногда это происходит на протяжении нескольких запросов от одного и того же пользователя – один запрос маршрутизируется через Proxy A, следующий запрос – через Proxy B и т. д. В этом случае сетевой коммутатор рассматривает эти запросы как запросы от разных пользователей (несмотря на то что это не соответствует действительности), в результате чего этот пользователь теряет состояние своего приложения, если вы заранее не распределили сессию между ячейками (или центрами обработки данных).

В описываемом решении применяется основанная на контенте маршрутизация, реализуемая с помощью сетевого коммутатора, который является IP-устройством 7-го сетевого уровня. Метод состоит в извлечении для каждого сервера идентификатора Server CloneID (см. ниже) из файла plugin-cfg.xml (используется плагином HTTP-сервера) и последующем использовании этого идентификатора при построении правил родственности для каждой ячейки. После этого сетевой коммутатор может исследовать заголовок входящего HTTP-запроса и определить, к какой ячейке он должен маршрутизировать этот запрос. В следующем примере демонстрируется правило для исследования заголовка HTTP-запроса на наличие идентификатора «13j9n75hm».

<Server CloneID="13j9n75hm" ConnectTimeout="0" ExtendedHandshake="false" LoadBalanceWeight="2" MaxConnections="-1"

Выполнение этой процедуры для каждого идентификатора CloneID в файле plugin-cfg.xml каждой ячейки и ассоциирование каждого идентификатора CloneID с определенной ячейкой посредством правила маршрутизации избавляет от необходимости совместного использования сессии несколькими ячейками – по крайней мере, по этой причине.

Идентичные клоны?
Предполагается, что все идентификаторы Server CloneID должен быть уникальными с точки зрения ячеек. Однако не существует какого-либо способа, позволяющего продукту Network Deployment гарантировать, что дело будет обстоять именно так. По указанной причине вам следует убедиться в отсутствии каких-либо дубликатов между ячейками. В случае выявления таких дубликатов просто удалите и обновите соответствующий сервер, в результате чего дублирование будет устранено. Идентификатор Server CloneID сервера приложения представляет собой хешированное время его создания (с точностью до миллисекунды). Таким образом, если вы по какой-либо случайности не умудрились создать в одно и то же время два сервера приложений в разных ячейках, то, скорее всего, вы не обнаружите каких-либо дубликатов. Как говорится, для полной уверенности необходимо все проверять и перепроверять. Если вы все же столкнетесь с дублирующимися идентификаторами CloneID в двух разных ячейках, то вам пора подумать о приобретении лотерейного билета!

Конечно, некоторые оппоненты будут утверждать, что реализация основанной на контенте маршрутизации обходится «слишком дорого» с точки зрения накладных расходов на сетевой коммутатор (и времени ожидания). Я не буду оспаривать тот факт, что это дорого, однако замечу следующее. Если вы не будете делать этого на фронтальном интерфейсе для входящих запросов, то, в конце концов, вам придется «заплатить больше» – посредством добавления сетевых ресурсов на серверной части для репликации данных HttpSession. Кроме того, вы создадите взаимозависимости внутри центра обработки данных, которые могут снизить надежность каким-либо иным образом.

При использовании описанного выше подхода родственности вы остаетесь уязвимыми только перед потерей сессии в случае внеплановой остановки. Это объясняется тем, что в случае плановой остановки вы сможете «опустошить» одну ячейку с помощью описанных в следующей статье методов поддержания непрерывной готовности (EN), в результате чего существующие пользователи останутся в первичной ячейке, а новые пользователи будут направляться в ячейку, недавно ставшую активной. С практической точки зрения, большое число внеплановых остановок – это признак каких-то фундаментальных проблем, нуждающихся в разрешении. В первую очередь необходимо выявить первопричину этих внеплановых остановок, по крайней мере, я поступил бы именно так. Дополнительное усложнение в результате разделения сессии между ячейками – в полном соответствии с инженерными принципами обеспечения надежности – с большой вероятностью будет приводить к дополнительным отказам, а те, в свою очередь, приведут к внеплановым остановкам, т. е. именно к тому, чего вы пытались избежать в первую очередь!


Благодарности

Выражаю благодарность Кейзу Ботзуму (Keys Botzum) и Алексу Полозову (Alex Polozoff) за их комментарии и предложения.

Ресурсы

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



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

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=WebSphere
ArticleID=398933
ArticleTitle=Серия «Альтернативное мнение по продуктам WebSphere»: Назад к основам: Аварийное переключение сессии
publish-date=06232009