среда, 2 марта 2011 г.

Создаем кластер серверов приложений WebLogic: балансировка нагрузки, обнаружение ошибок, репликация сессий


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

В данной статье мы рассмотрим следующие вопросы:
  1. Структура домена WebLogic.
  2. Создание домена и объединение серверов в кластер.
  3. Балансировка нагрузки с помощью HttpClusterServlet.
  4. Репликация сессий между серверами кластера.
  5. Балансировка нагрузки с помощью Apache 2.
  6. Выводы.
  7. Ресурсы.


Структура домена WebLogic


Разберемся с терминами:
Домен - группа серверов приложений, администрируемая как единое целое с помощью единственного администрирующего сервера (Admin Server). Сервера, компоненты домена, не являющиеся администрирующим сервером, называются управляемыми серверами (Managed Servers). Управляемые сервера, объединенные в домен, могут быть сгруппированы в несколько кластеров.



Кластер - группа управляемых серверов, между которыми возможна балансировка нагрузки и репликация сессий.

Стоит отметить, что управляемые сервера можно не объединять в кластер, однако между необъединенными в кластер серверами невозможно реплицировать сессии.

Создание домена и объединение серверов в кластер


Для управления доменом предназначена специальная утилита, расположенная по адресу (в Windows, %WL_HOME% обозначает каталог, в который установлен WebLogic) %WL_HOME%\common\bin\config.cmd.

После запуска данная утилита предложит на выбор два варианта: создание нового или модификация существующего домена. Нам необходимо создать новый домен:



Существует три варианта создания домена:
  • с нуля;
  • по шаблону;
  • использование автоматически созданной конфигурации для поддержки определенного продукта.
В данном случае создадим домен с нуля: Для домена необходимо задать имя и указать каталог, в котором он будет создан: После чего указать информацию об администраторе домена: логин, пароль и описание: На следующем шаге необходимо выбрать режим работы домена: Development или Production. Первый, как следует из названия, предназначен для разработки: оптимизирован процесс запуска серверов и упрощен процесс разворачивания приложений, второй вариант же оптимизирован по производительности. На данном шаге так же необходимо выбрать JDK, который будет использовать домен: Дополнительные параметры конфигурации включают в себя указание на то, будет ли модифицироваться информация об администрирующем сервере и будут ли включаться в домен управляемые сервера. Так же возможен вариант хранения в БД информации, касающеся безопасности домена и приложений, но в данном примере мы не будем ею пользоваться: Следующие несколько шагов мастера создания домена предназначены для модификации сведений об администрирующем сервере и добавления кластера/управляемых серверов. Для администрирующего сервера необходимо указать название, адрес и порт, которые данный сервер будет использовать, а так же, при необходимости, включить поддержку SSL и порт, на который сервер будет принимать запросы по HTTPS: Для добавления управляемых серверов существует удобная таблица, позволяющая задавать название, адрес и порт каждому серверу. При необходимости можно включить SSL, так же, как и для администрирующего сервера: После создания управляемых серверов их можно объединить в один или несколько кластеров: После создания управляемых серверов и кластера необходимо задать соответствие между серверами и физическими машинами. На одной физической машине может быть запущено несколько копий WebLogic - т.е. несколько серверов. Каждая машина представляет собой т.н. "ноду", управляемую специальным сервисом - Node Manager'ом. Стоит отметить, что Node Manager относится именно к машине, а не к домену, т.е. одна машина может входить в несколько доменов. На данной странице задаются названия и адреса машин, а так же номера портов, которые на каждой машине слушает Node Manager. Наличие Node Manager'а позволяет администраторам управлять серверами, входящими в домен, с помощью консоли администрирования домена: На последнем шаге работы мастера представлены все сведения о создаваемом домене, если эти сведения нас устраивают, то необходимо нажать кнопку Create и подождать некоторое время, пока домен будет создаваться. После создания домена необходимо запустить административный сервер с помощью команды %DOMAIN_HOME%\bin\startWebLogic.cmd. После запуска сервера будет доступна его консоль администрирования, расположенная по адресу http://localhost:7001/console/. В данной консоли необходимо перейти по адресу Servers/Control и запустить управляемые сервера: После того, как все управляемые сервера будут запущены, можно разворачивать демонстрационное приложение на кластере, для чего обратиться к пункту меню Deployments: Выбрать разворачиваемое приложение... Обязательно развернуть приложение на всем кластере... Развернутое приложение отобразится в списке. Необходимо убедиться, что его состояние - Active, а Health - OK: Итак, мы имеем домен, в котором присутствует кластер серверов, на которых, в свою очередь, развернуто демонстрационное приложение. Теперь необходимо настроить балансировку нагрузки между серверами кластера.

Балансировка нагрузки с помощью HttpClusterServlet

В качестве балансировщика нагрузки может выступать как аппаратное решение, так и специальный сервлет - weblogic.servlet.proxy.HttpClusterServlet или веб-сервер Apache 2. Последние два варианта мы и рассмотрим в рамках данной статьи. Прежде чем использовать решение на основе weblogic.servlet.proxy.HttpClusterServlet, необходимо создать дополнительный домен, содержащий один - администрирующий - сервер, на котором будет развернут веб-модуль, предоставляющий доступ к HttpClusterServlet'у. Условимся, что данный сервер будет доступен на порту 9001: Сам сервлет HttpClusterServlet поставляется вместе с WebLogic, однако его необходимо настроить, описав в дескрипторе развертывания web.xml. Полный список настроек приведен в официальной документации, ограничимся лишь минимальным набором: указанием серверов, между которыми распределяется нагрузка и констатацией того факта, что защищенное соединение не используется:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">     <servlet>         <servlet-name>HttpClusterServlet</servlet-name>         <servlet-class>weblogic.servlet.proxy.HttpClusterServlet</servlet-class>         <init-param>             <param-name>WebLogicCluster</param-name>             <param-value>localhost:8001|localhost:8002|localhost:8003</param-value>         </init-param>         <init-param>             <param-name>SecureProxy</param-name>             <param-value>OFF</param-value>         </init-param>     </servlet>     <servlet-mapping>         <servlet-name>HttpClusterServlet</servlet-name>         <url-pattern>/</url-pattern>     </servlet-mapping> </web-app>
Следует обратить внимание, что на конкретный сервер будут перенаправляться все запросы:
<url-pattern>/</url-pattern>
Чтобы балансировка нагрузки работала корректно, необходимо развернуть веб-модуль, предоставляющий доступ к HttpClusterServlet, в корневой веб-контекст, т.е. модуль должен быть доступен по адресу http://localhost:9001/, а не http://localhost:9001/something. Указать путь к веб-контексту необходимо в дополнительном, специфичном для WebLogic, дескрипторе развертывания - weblogic.xml:
<?xml version="1.0" encoding="UTF-8"?> <wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.1/weblogic-web-app.xsd">     <wls:weblogic-version>10.3.3</wls:weblogic-version>     <wls:context-root>/</wls:context-root> </wls:weblogic-web-app>
Созданный веб-модуль, по сути содержащий лишь два дескриптора развертывания, необходимо развернуть (прошу прощения за тавтологию) на единственном, администрирующем, сервере второго из созданых нами доменов. Теперь можно протестировать балансировку нагрузки в действии. Демонстрационное приложение, развернутое на кластере, содержит в себе сервлет, выводящий наименование сервера, обрабатывающего запрос. Данный сервлет доступен по адресу http://localhost:9001/oracle-cluster-demo/cluster: Видно, что запрос был обработан на сервере NL1. Обновим страницу: Теперь - на сервере NL3. И NL2. По-умолчанию используется алгоритм Round-Robin, т.е. по сути запросы перенаправляются на каждый сервер по кругу. В состав демонстрационного приложения так же входит страница, написаная на JSF: Если обновлять данную страницу или нажимать кнопку Update, то ничего происходить не будет - запрос будет по-прежнему перенаправляться на сервер NL2. Дело в том, что в WebLogic реализована балансировка нагрузки с привязкой к сессии. Т.е. если инициирована сессия (а JSF всегда инициирует сессию для хранения состояния страниц), то все последующие запросы будут направляться на сервер, иницировавший эту сессию. В нашем примере - на сервер NL2. Однако, для демонстрации можно открыть новую сессию, например обратившись к странице http://localhost:9001/oracle-cluster-demo/info.jsf из другого браузера. Посмотрим, что произойдет если имитировать сбой на сервере NL2, например отключив его: Т.к. обратиться к серверу NL2 нельзя - он выключен - то балансировщик перенаправит запрос на другой сервер, но на другом сервере нет данных сессии, что приводит к 500-й ошибке:

Репликация сессий между серверами кластера

Чтобы избежать подобных ошибок, необходимо настроить репликацию данных о пользовательских сессиях между узлами кластера. Нужно отметить, что WebLogic поддерживает довольно широкий диапазон возможных хранилищ данных сессий:
  • InMemory - применяется для одиночного сервера, данные хранятся в памяти, не реплицируются.
  • InMemory Replication - данные хранятся в памяти, но реплицируются между серверами в кластере.
  • File system persistence - данные хранятся в файловой системе сервера. Репликацию можно сделать через общее файловое хранилище.
  • JDBC persistence - данные хранятся в базе данных. Поддерживаются Oracle, SQL Server, Sybase, DB2 и другие типы СУБД.
  • Cookie-based session persistence - данные хранятся на машине клиента. Метод накладывает ряд ограничений - поддерживается только basic-авторизация, в сессии можно хранить только строки и т.д.
Необходимый тип хранения/репликации указывается в качестве значения параметра wls:session-descriptor/wls:persistent-store-type дескриптора развертывания weblogic.xml. Данный параметр может принимать следующие значения:
  • memory — данные сессии хранятся в памяти сервера и не реплицируются;
  • replicated — данные сессии хранятся в памяти сервера и реплицируются между серверами кластера. При попытке развернуть приложение на одиночном сервере будет брошено исключение;
  • replicated_if_clustered — если приложение разворачивается в кластере, то данные сессии будут реплицироваться между машинами кластера, иначе - храниться в памяти сервера;
  • async-replicated - асинхронная репликация данных между машинами кластера;
  • async-replicated-if-clustered - асинхронная репликация данных между машинами, если приложение разворачивается на кластере, иначе - данные будут храниться в памяти сервера;
  • file — данные сессии хранятся в файловой системе сервера;
  • async-jdbc — асинхронное помещение данных в СУБД;
  • jdbc — синхронное помещение данных в СУБД;
  • cookie — все данные сессии хранятся в куках пользовательского браузера.
Установим для нашего приложения тип хранилища replicated:
<wls:session-descriptor>     <wls:persistent-store-type>replicated</wls:persistent-store-type> </wls:session-descriptor>
После чего, повторим эксперимент с выключением сервера. Увидим, что даже после смены сервера данные сессии успешно прочитаны и состояние JSF-страницы восстановлено:

Балансировка нагрузки с помощью Apache 2

Использовать для балансировки нагрузки целый отдельный домен, а тем более отдельный сервер WebLogic довольно накладно. Однако, WebLogic поддерживает целый ряд серверов, таких как Apache 2 и даже IIS, позволяя использовать их в качестве балансировщика. Рассмотрим использование веб-сервера Apache 2 для обработки статического контента и балансировки нагрузки. Прежде всего необходимо скачать веб-сервер с официального сайта и установить. После чего добавить к веб-серверу модуль mod_wl_22.so (или mod_wl128_22.so, если нужно использовать 128-битную криптографию). Для этого нужно скопировать файл (для Windows 32) %WL_HOME%\server\plugin\win\32\mod_wl_22.so в каталог %APACHE_HOME%\modules и отредактировать файл %APACHE_HOME%\conf\httpd.conf, добавив в него строчку:
LoadModule weblogic_module modules/mod_wl_22.so
Данную строчку нужно добавить в начало списка подключаемых модулей. Возможны два варианта анализа запроса - по пути и по MIME-типу запрашиваемого контента. Для диспетчеризации по пути используются элементы конфигурационного файла Apache
<Location /weblogic>
Для диспетчеризации по MIME-типу - элементы файла конфигурации Apache
<IfModule mod_weblogic.c>
Для нашего минимального примера достаточно добавить в конец файла httpd.conf следующие строки:
<IfModule mod_weblogic.c>   WebLogicCluster localhost:8001,localhost:8002,localhost:8003   MatchExpression *.jsf   WLLogFile         C:/Windows/Temp/foo_proxy.log </IfModule>
Здесь:
  • WebLogicCluster - список серверов, на которые можно перенаправлять запросы. Следует обратить внимание, что сервера могут и не являться частью кластера, но тогда между ними будет невозможна репликация данных сессии;
  • MatchExpression - MIME-тип, подвергающийся диспетчеризации. Если нужно обрабатывать несколько типов - должно быть несколько записей MatchExpression.
  • WLLogFile - путь к файлу логу ошибок диспетчеризации.
Если теперь обратиться по адресу http://localhost/oracle-cluster-demo/info.jsf, то получим примерно следующее: Т.к. на сервера WebLogic перенаправляются запросы только к JSF-страницам, то статический контент недоступен. Чтобы статический контент стал доступен, необходимо в каталоге ServerRoot/htdocs/ сервера Apache создать каталог, название которого совпадает с root-context'ом приложения (например, oracle-cluster-demo), в который и скопировать весь статический контент приложения. Теперь раздавать статический контент будет веб-сервер Apache, снижая при этом нагрузку на WebLogic-кластер. Список серверов, указанный в настройках конфигурации, является базовым. Если во время работы приложения сервера выключают или добавляют новые, то в каждом ответе от WebLogic-сервера Apache'у приходит новый список серверов. Стоит помнить, что идентификатор сессии содержит ссылку на сервер, который инициировал эту сессию. Поэтому все запросы в рамках сессии будет обрабатывать один и тот же сервер. Такой сервер называется первичным (primary). С первичным сервером проассоциирован т.н. вторичный сервер (secondary), между этими серверами происходит репликация данных сессии. Если первичный сервер выходит из строя, то из списка доступных серверов по алгоритму Round-Robin выбирается новый сервер, который становится первичным. Этот сервер запрашивает данные сесии у вторичного сервера и продолжает обрабатывать запросы. Если же произойдет одновременное падение и первичного и вторичного серверов, то данные сессии будут утеряны. Схема данного алгоритма восстановления после ошибки приведена на рисунке:

Выводы

Мы рассмотрели структуру домена WebLogic и разобрались как настроить балансировку нагрузки, восстановление после ошибки и репликацию сессии между узлами кластера. Вне рассмотрения остались проблемы выбора кластерной топологии и балансировка нагрузки не в веб-части приложения, а на уровне бизнес-логики (EJB), инфраструктуры (RMI, JMS) и хранения данных (JDBC). Если будет необходимо, то рассмотрим данные аспекты позднее. Как всегда буду рад ответить на ваши вопросы, задавайте их в комментариях.

Ресурсы

Понравилось сообщение - подпишитесь на блог

25 комментариев:

Mikhail Krestjaninoff комментирует...

Спасибо за статью! Я правильно понимаю, что решение проблемы общей файловой системы для элементов домена (управляемых серверов) остаётся вне компетенции кластера WebLogic. Другими словами у нас нет возможности горизонтально масштабировать приложение, работающее с файлами, только по средствам WebLogic?

Pavel Samolisov комментирует...

Могу ошибаться, но похоже нет. В сети активно обсуждают решения на основе NFS, Red Hat GFS, drbd.

З.Ы. добавил еще одну ссылку в Ресурсы.

Bura комментирует...

Павел, а есть ли какие нибудь стандартные средства для сборки и/или развертывания приложений на кластер, балансируемый с помощью веб сервера Apache? Т.е. можно ли получить war без статических ресурсов и еще отдельно что то типа zip архива со статическими ресурсами? Что бы можно было бы war развернуть в кластере и zip в веб сервере. Или как вообще такие задачи решаются?

Pavel Samolisov комментирует...

Таких специализированных средств я не знаю, однако все можно решить, например, с помощью старого доброго Ant'а - WebLogic предоставляет антовские команды для развертывания модулей на кластере.

В конце-концов технология J2EE модульная и никто не мешает просто создавать отдельные проекты: проект со статикой, собираемый в ZIP, проект с веб-модулем - в WAR, EJB модули - в ZIP и так далее. Веб-интерфейс службы администрирования WebLogic позволяет разворачивать модули как на кластере, так и на отдельных серверах.

Bura комментирует...

Мой рецепт (через maven):
1) war собираю спомощью maven-war-plugin, с исключением статических ресурсов;
2) статические ресурсы заворачиваю в zip с помощью maven-assembly-plugin;
3) Полученные на выходе файлы раскладываю куда нужно в ручную (хотя тоже можно было бы автоматизировать).

Pavel Samolisov комментирует...

Спасибо за рецепт.

Пункт 3 в крайнем случае можно попробовать автоматизировать через maven-ant взаимодействие.

Евгений Поляков комментирует...

"Стоит отметить, что управляемые сервера можно не объединять в кластер, однако между необъединенными в кластер серверами невозможно распределять нагрузку"

Возможно.

Pavel Samolisov комментирует...

Спасибо за ценное замечание. Внес изменения.

Alexander комментирует...

А работает ли репликация если использовать в качестве балансировщика Oracle HTTP Server?

Pavel Samolisov комментирует...

Сам не настраивал, поэтому определенно сказать не могу. Если я не путаю и Oracle HTTP Server - компонент Oracle WebTier, то это тот же Apache, но с поддержкой от Oracle.

Alexander комментирует...

Да, согласен. Просто странно, что примеров с использованием OHS нигде нет, хотя Webtier покрывается лицензией от Weblogic.
Хотел бы еще уточнить. Например при использовании трех серверов в кластере получается трехкратное резервирование.
Но не понятно, как резервируется сам балансировщик. Ведь он должен находится на одном из серверов кластера, если это софтовое решение. Т.е. никакого резервирования балансировщика нет. А без него не работает кластер. Немного странно.

Pavel Samolisov комментирует...

Я видел такое решение: стояло два балансировщика на двух отдельных узлах (т.е. даже не тех машинах, которые входят в кластер). Балансировка же между балансировщиками осуществлялась на уровне DNS.

Alexander комментирует...

Спасибо. Может можете порекомендовать какой-то ресурс или книгу, где рассматривались бы вопросы проектирования инфраструктур на weblogic или в общем касательно oracle-инфраструктур? Что-то типа best practice.

Pavel Samolisov комментирует...

Есть книжка Professional Oracle WebLogic Server. Есть блоги и конечно же форумы OTN. Какой-то конкретной статьи не подскажу, т.к. инфраструктуру нужно проектировать под конкретно вашу задачу, а лучше вас ее никто не знает.

Alexander комментирует...

А можно еще уточнить?
Можно ли использовать Apache или OHS как балансировщик для нескольких кластеров?
Т.е. необходимо, чтобы Apache слушал несколько портов. Не знаю, можно ли это сделать с помощью virtual hosts?

Pavel Samolisov комментирует...

По поводу портов - затрудняюсь с ответом. Виртуальные хосты, думаю, следует попробовать.

Alexander комментирует...

Павел, а можно ли сделать балансировку между серверами кластера не просто через round-robin,
а определяя наименее загруженный сервер?

Pavel Samolisov комментирует...

@Alexander, в кластере есть параметр - Default Load Algorithm. По-умолчанию, его значение равно round-robin. Посмотрите, там есть разные варианты, в частности weight-based и random.

Alexander комментирует...

Павел, а можно еще вопрос.
Ввиду того, что "mod_wl_ohs (as of 11gR1) only support container level failover and NOT application level failover. mod_wl_ohs continues to route requests to a down application as long as the managed server is up and running." Думаю, это характерно не только для Oracle HTTP Server.
Есть ли механизм, который обеспечит именно защиту приложения?

Pavel Samolisov комментирует...

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

Как решать данную задачу относительно отдельного приложения я не знаю, не интересовался.

Alexander комментирует...

Павел, да, согласен. Хотел бы последний вопрос задать. Где можно скачать тестовое приложение, показывающие работу балансировщика, приведенное в статье?

Pavel Samolisov комментирует...

К сожалению, у меня не осталось исходников тестового приложения.

Dmitrii комментирует...

А зачем для HttpClusterServlet сервлета создавать отдельный домен? ведь его можно установить на отдельный новый managed сервер(не в кластере) в созданном домене.

Pavel Samolisov комментирует...

Да, можно и так сделать. Просто отдельный домен был удобнее для демонстрации - когда меняем балансировщик, наш домен с кластером не захламляется ненужным MS.

areful комментирует...

Павел приветствую.

Приходилось ли Вам настраивать подобную схему:
Клиент -> OHS -> Weblogic
Клиент через прокси (OHS в моем случае) заходит на Weblogic по SSL сертификату, который OHS должен пробрасывать на Weblogic.

Дело в том, что вход по сертификату напрямую на weblogic настраивается без проблем, через Default Asserter. Однако как только между клиетом и сервером появляется прокси, то на сам OHS клиент попадает, однако на Weblogic его не пробрасывает. Может быть что-то подскажете?
Заранее благодарен.

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

Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!