Блог компании Jelastic / Один в поле не воин: как создать отказоустойчивый кластер

в 8:17, , рубрики: glassfish, high availability, java, jelastic, nginx, postgresql, кластер

Часто случается, что после запуска какого-нибудь амбициозного интернет проекта и удачного его пиара в СМИ компания ожидает большой приток посетителей. К сожалению, наш мир не идеален и так случается, что сайт не справляется с таким потоком посетителей, называемым в наших кругах «хабраэффектом», и начинает тормозить. Соответственно компания теряет и деньги и репутацию. В таких случаях программисты обычно сваливают вину на админов, а админы на программистов. Получается замкнутый круг.

imageЧто же делать, если ваше приложение стало тормозить? Одним из способов является перевод его в <a rel="nofollow" href="http://habrahabr.ru/company/jelastic/blog/136996/">кластерную архитектуру. К сожалению, есть не так много инструкций и статей, которые подскажут, как это сделать. Поэтому мы решили опубликовать небольшой пример того, как можно создать отказоустойчивый кластер на базе GlassFish. Этот процесс и многое другое автоматизировано в Jelastic, но если Вы по каким-либо причинам не можете перейти на облачный хостинг, то эта статья именно для Вас.
Давайте начнем по порядку:

Подготовка

Для создания отказоустойчивого кластера нам понадобятся: две машины n1 и n2 для серверов GlassFish (на одну из них будет установлен DAS и 2 сервера GF); машина lb1 для балансировки нагрузки; машина db1 для СУБД. Убедитесь, что все машины «видят» друг — друга (ping).

Все ПО будет работать под управлением Linux. Будем использовать заранее подготовленный образ виртуальной машины с CentOS. GlassFish использует для управления удаленными нодами SSH, поэтому нам потребуется установленный SSH-сервер на каждой из машин кластера. Также для возможности работы по SSH нам потребуется отдельная учетная запись в каждой ОС. Предлагаю назвать ее единообразно для всех машин: glassfish.
# adduser glassfish
# passwd glassfish

GlassFish использует нестандартные порты и для того, чтобы с ним можно было работать с помощью админ консоли в браузере, нужно либо прописать соответствующие правила в firewall, либо вообще его отключить. Предлагаю сделать последнее:
# service iptables save
# service iptables stop
# chkconfig iptables off

Ну и, конечно же, без JVM нам не обойтись.
Предупреждаю сразу, что придется прилично повозиться, так как требуется большое количество настроек.
image

Конфигурация кластера

Конфигурацию кластера будем проводить преимущественно из командной строки с помощью утилиты из поставки GlassFish asadmin

  1. Скачиваем дистрибутив GlassFish
    wget download.java.net/glassfish/3.1.1/release/glassfish-3.1.1.zip
    и распаковываем его.
  2. Запускаем экземпляр административного домена (domain1):
    ./asadmin start-domain domain1
    GlassFish по умолчанию запрещает удаленные подключения к административному домену. И все узлы кластера (Node Agents), кроме того узла, на котором стоит DAS, не смогут с ним взаимодействовать.
    Типичная ошибка:
    Failed to rendezvous with DAS on n1:4848. Please check if this server is running, that the host and port are correct, and that this server is configured to allow remote access.
    Чтобы это обойти выполняем:
    ./asadmin enable-secure-admin
    и перезапускаем административный домен.
    Создаем сам кластер:
    ./asadmin create-cluster c1.
    Создаем два экземпляра сервера приложений, находящихся на этой же физической машине:
    ./asadmin create-local-instance --cluster c1 i1
    ./asadmin create-local-instance --cluster c1 i2
  3. Запускаем кластер:
    ./asadmin start-cluster c1
  4. Добавляем новые экземпляры, находящиеся на машине n2 (команды физически выполняються на n2):
    ./asadmin –host n1 –port 4848 create-local-instance –cluster c1 i3
    ./asadmin –host n1 –port 4848 create-local-instance –cluster c1 i4
  5. В админ консоли находим вновь созданный экземпляр, меняем его тип на SSH, меняем значение поля Node Host на n2. При этом нам необходимо указать имя пользователя и его пароль для доступа по SSH на машину n2. Запускаем кластер. Видим, что все экземпляры работают.

image

Балансировка нагрузки и HA

Сейчас фактически все готово для того, чтобы задеплоить приложение в кластер, но для нас этого мало, т.к. не обеспечена балансировка нагрузки и HA.
Нам необходимо установить и настроить балансировщик нагрузки для того, чтобы пользователям было удобно работать с приложением:

  • обращались только по одному урлу;
  • их запросы распределялись равномерно по всем экземплярам серверов кластера;
  • в случае выхода из строя некоторого количества экземпляров пользователи смогли бы продолжить работу с приложением в штатном режиме;
  • и вообще не знали о внутренней «кухне» кластера.

Вообще GlassFish «содержит» плагин балансировки для «популярных» http-серверов. Слова «содержит» и «популярных» не зря взяты в кавычки, т.к. данный плагин не содержится в Open Source версии GF, к тому же поддерживаются Oracle iPlanet Web Server,Oracle HTTP Server, Apache HTTP Server, Microsoft IIS. Все мы знаем, что Apache был когда-то хорош, но сейчас есть более эффективные решения.
Среди кандидатов: NGINX, HAProxy, lighthttpd.
Поддержим отечественного производителя и выберем NGINX, который к тому же все больше и больше захватывает рынок.

  1. Устанавливаем NGINX:
    #yum install nginx
    #nano /etc/nginx/nginx.conf
  2. Настраиваем NGINX на балансировку запросов round-robbin для 4х серверов одинаковых весов c поддержкой закрепленных (sticky) сессий (ниже приводится часть конфига и запускается сервер).
    upstream backend {
    ip_hash;
    server 192.168.0.1:28080 max_fails=5 fail_timeout=15s;
    server 192.168.0.1:28081 max_fails=5 fail_timeout=5s;
    server 192.168.0.2:28082 max_fails=5 fail_timeout=5s;
    server 192.168.0.2:28083 max_fails=5 fail_timeout=5s;
    }

    Стоит отметить, что это самый простой конфиг закрепляющий сессии пользователей за конкретным сервером по методу ip_hash
  3. Чтобы заработала HA необходимо, чтобы хосты n1 и n2 имели общий родительский домен. Например, cluster.com. Для этого нужно модифицировать файлы /etc/hosts на обеих машинах следующим образом:
    n1:
    127.0.0.1 localhost
    127.0.1.1 n1.cluster.com
    127.0.0.1 n1.cluster.com
    192.168.0.2 n2.cluster.com

    n2:
    127.0.0.1 localhost
    127.0.1.1 n2.cluster.com
    127.0.0.1 n2.cluster.com
    192.168.0.1 n1.cluster.com
  4. Для проверки работы multicast на каждой физической машине кластера выполняем:
    ./asadmin validate-multicast
  5. В административной консоли DAS GlassFish необходимо поменять упоминание n2 на n2.cluster.com
  6. Для того, чтобы GlassFish производил репликацию Http-сессий между экземплярами кластера необходимо, чтобы веб-дескриптор приложения содержал соответствующую инструкцию (тэг <distributable/>) и при деплое приложения установить флаг Avalaibility.

Установка и конфигурация БД

В данном примере будем использовать PostgreSQL.
Устанавливаем СУБД и создаем нового пользователя и базу данных.
# yum install postgresql-8.4
# service postgresql initdb
# service postgresql start

В PostgreSQL по умолчанию разрешены только локальные подключения. Для того, чтобы это исправить необходимо поправить конфигурационный файл /var/lib/pgsql/data/pg_hba.conf, в котором нужно указать разрешенные подсети: host all all 192.168.0.0/24 md5

Ну вот и все! Теперь наконец-то можно деплоить приложение (для примера мы используем jforum).
image

У меня, честно говоря, после всех этих настроек чуть не «вскипел мозг». Нам пришлось хорошенько «попотеть», чтобы автоматизировать весь описанный выше процесс в Jelastic и превратить его в несколько щелчков мышью.
image
Можете попробовать, что из этого вышло, на jelastic.com и поделиться мнением в комментариях к посту.
Автор:

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js