[spoiler]
Введение
Рассмотрим стандартную 2-х серверную конфигурацию для Web приложения с точки зрения надёжности и масштабируемости.
Для масштабирования Web серверов было бы правильно использовать независимый от конкретного сервера балансировщик нагрузки, обеспечивающий диагностику HTTPD сервисов – для обеспечения высокой готовности Web сервера. Такой иструмент уже есть на нашей схеме - Front end server nginx (который, как, наверное, большинство подобных инструментов умеет делать load balance и health check), но в нашей конфигурации он связан с конкретным оборудованием (Web сервер).
Сервер БД в этой конфигурации также не может рассматриваться ни как надёжный, ни как масштабируемый компонент системы.
При решении перечисленных задач предполагается использование стандартного общедоступного оборудования: x86_64 серверы, 1GB/sec Ethernet, недорогие дисковые массивы с интерфейсами NFS или Fiber Channel Protocol.
Oracle Clusterware
Для обеспечения надёжности и масштабируемости рассматриваемой Web системы предлагается использовать Oracle Clusterware – кластерное ПО, разрабатываемое и поддерживаемое Oracle в рамках программы Oracle Enterprise Linux Support не только для Oracle Real Application Cluster (RAC) и даже не только для RDBMS и приложений Oracle. В соответствии с
Как это работает
На серверы уставливается Oracle Enterprise Linux + Oracle Clusterware, при этом конфигурационные файлы кластера (Cluster Registry и Voting Disk) должны находится на внешней дисковой системе, подключённом к серверам по Fiber Channel Protocol (FCP), NFS, либо iSCSI и быть доступны любому кластерному серверу (ноду). Из дополнительного оборудования потребуется выделенное Ethernet соединение между серверами – Cluster interconnect (зелёная стрелка №3 на схеме).
Критические сервисы (nginx, httpd, сервер БД) входят в состав кластерных ресурсов (групп сервисов). Кластерные ресурсы объединяют и определяют взаимодействие связанных сервисов. При создании ресурсов пользователь определяет: зависимость между отдельными сервисами, разрешённые для запуска сервисов кластерные ноды, программу запуска/остановки/проверки статуса сервиса, параметры перезапуска сервисов, периодичность контроля их статуса и т.д. Важно отметить, что скрипт запуска, остановки и проверки статуса сервиса пользователь может подготовить самостоятельно (использовав perl, sh, любой другой язык) или использовать готовые шаблоны, подготовленные Oracle (perl).
Для нашей задачи достаточно будет определить следующие кластерные ресурсы:
1) «Кластерный ресурс NGINX+VIP» состоит из виртуального IP адреса (VIP) и зависящего от него сервиса NGINX (т.е. кластерное ПО не будет стартовать nginx на сервере, пока VIP не будет успешно запущен на этом же сервере). Этот кластерный ресурс может быть поднят на любом ноде кластера в результате «ручной операции» перемещения, либо failover на рабочий нод кластера (красная стрелка №1 на схеме) после исчерпания определённого при создании ресурса лимита попыток рестартовать сервис на первом ноде, либо в случае недоступности первого нода. Виртуальный IP адрес приложения в этом случае служит внешним адресом нашего Web приложения, а NGINX выполняет роль кэширующего прокси-сервера и балансировщика нагрузки между доступными серверами Apache.
2) «Кластерный ресурс HTTPD» конфигурируется на каждом сервере кластера как неперемещаемый ресурс: кластерное ПО не будет пытаться переместить этот ресурс между серверами. В случае, если статус этого ресурса не «ОК», кластерное ПО будет пытаться перезапустить httpd сервер на «родном» ноде определённое при конфигурации количество раз. Файлы сайта могут храниться локально на серверах с периодической репликацией, на сетевой или кластерной файловой системе (NFS, GFS). Соединение с БД HTTPD сервер осуществляет по виртуальному IP адресу БД.
3) Сервер MySQL входит в состав «Кластерного ресурса БД», который состоит из виртуального IP БД, процесса монтирования некластерной файловой системы БД и сервера MySQL. При этом, конфигурация этого ресурса определяет следующую зависимость между компонентами: запуск сервера MySQL зависит от монтирования файловой системы, которая, в свою очередь, зависит от присутствия на сервере виртуального IP БД. Ресурс перемещаемый, может быть перемещён (вручную, или в результате файловера, см. красную стрелку №2 на схеме) на любой доступный нод кластера.
Высокая готовность (High Availability)
В описанной конфигурации остановка работы любого компонента системы (от отдельного сервиса до любого из серверов) не приводит к прекращению работы нашего Web приложения.
Статус всех кластерных сервисов проверяется с заданной периодичностью, в случае проблем (статус сервиса <> ОК) кластерным ПО будет сделано определённое при создании количество попыток перезапустить сервис, и в случае неуспеха, сервис вместе со своим кластерным ресурсом будет перемещён на следующий доступный нод кластера.
Статус кластерных нодов(серверов) также постоянно мониторится и, в случае недоступности, сервер перезагружается, а кластерные ресурсы перемещаются на работоспособный сервер.
Требуемый уровень надёжности дискового массива достигается грамотным выбором оборудования (дублированные блоки питания, вентиляторы, контроллеры, использование RAID). Стоимость такого массива сравнима со стоимостью 2-х процессорного сервера (от 150 т.р.). Надёжность соединений между оборудованием нашего кластера (TCP/IP, FCP) может быть обеспечена на уровне ПО и оборудования (NIC bonding, trunking, FC multipathing), что не является обязательным условием построения отказоустойчивого решения, поскольку выход из строя ЛЮБОГО компонента может привести к отказу только ОДНОГО кластерного нода. Кластерные сервисы продолжат функционировать на оставшихся нодах.
Масштабирование Web части
На уровне web серверов, масштабирование может быть достигнуто добавлением в кластер серверов с установленными HTTPD службами и соответствующим изменением конфигурации nginx для распределения нагрузки на новые серверы. Обе операции могут быть выполнены online, не прерывая работы Web приложения в соответствии с документацией Oracle Clusterware и
Масштабирование MySQL
Использование Oracle Clusterware обеспечивает высокую готовность сервера MySQL. Достижение практической масштабируемости с использованием репликации (master-master, master-slaves, циклической) представляется отдельной непростой задачей и потребует существенного изменения кода приложения Bitrix. Использование MySQL Cluster в настоящий момент не представляется удачной идеей по причине низкой производительности на стандартном оборудовании – см.
Масштабирование Oracle
При использовании Oracle Clusterware масштабирование БД Oracle будет естественно несложной задачей и может выполняться поэтапно в зависимости от потребностей клиента (нагрузки на сайт):
I. На первом этапе на кластер можно установить некластерную БД Oracle Standard Edition One (до 2-х процессоров) в режиме высокой готовности.
Для управления файлами БД требуется использовать Oracle ASM (обязательное лицензионное требование Standard Edition) в кластерном режиме, либо в обычном режиме в составе «Кластерного ресурса БД». Использование Oracle ASM избавляет от необходимости заботиться об исключении одновременного доступа к файлам БД при монтировании файловой системы.
Сервер БД (Oracle instance) будет функционировать как обычный кластерный ресурс (не Oracle RAC), который в случае проблем будет перемещён на доступный кластерный нод (красная стрелка №2).
Эта конфигурация потребует, кроме поддержки Oracle Linux, лицензировать Oracle SE1 (от 1 до 2-х процессоров по цене $5800 + тех.поддержка $1276 за процессор, независимо от количества ядер). В максимальной конфигурации (2-х процессорный сервер, до 12 ядер) стоимость лицензий Oracle составит 2*$5800=$11600, стоимость ежегодной техподдержки 2*$500+2*$1276=$3552.
Для того, чтобы значительно загрузить такой сервер БД, Веб проект на Битрикс должен иметь сложную бизнес-логику и испытывать очень высокие нагрузки (миллионы хитов, сотни тысяч посетителей в сутки).
II. Следующим этапом масштабирования может быть переход на Oracle Standard Edition – до 4 процессоров. Эту редакцию Oracle можно использовать либо в режиме высокой готовности (как описано выше, никакого обновления ПО, только добавление процессоров или замена серверов), либо в режиме Oracle RAC (также до 4-х процессоров в системе, потребуется обновление ПО и файлов БД).
В случае RAC серверы БД (Oracle instance) будут работать одновременно на 2-х кластерных нодах. Балансировка подключений от Web производится автоматически в заданном режиме, общие файлы БД находятся под управлением Oracle ASM на разделяемом кластерном массиве.
Стоимость лицензий Oracle в максимальной конфигурации (4 процесса в системе, до 24 ядер) составит 4*$17,500=$70,000, стоимость ежегодной техподдержки 2*$500+2*$3,850=$16,400.
Поскольку мне трудно представить себе Веб проект, способный значительно загрузить такой сервер БД, варианты дальнейшего масштабирования (Oracle Enterprise Edition) рассматривать [пока] нет необходимости.
Практические рекомендации
Для развёртывания кластера высокой доступности с использованием MySQL в качестве разделяемого дискового массива может оказаться достаточно использовать сервер с архитектурой x86_64 и установленной ОС Linux и службой NFS.
В соответствием с рукодством по
При подготовке кластерных ресурсов, используем
Готовим виртуальный IP веб-приложения (nginx.vip). Для этого используем уже подготовленный Oracle скрипт управления VIP - $ORA_CRS_HOME/bin/usrvip, виртуальный IP 192.168.0.208 (netmask 255.255.255.0) у нас будет связан с сетевым интерфейсом eth0. При создании этого ресурса мы не указываем доступные для его запуска кластерные ноды ( ключ –h команды crs_profile -create), т.е. ресурс может стартовать на любом доступном ноде:
$ORA_CRS_HOME/bin/crs_profile -create nginx.vip -t application -a $ORA_CRS_HOME/bin/usrvip -o oi=eth0,ov=192.168.0.208,on=255.255.255.0 $ORA_CRS_HOME/bin/crs_register nginx.vip $ORA_CRS_HOME/bin/crs_setperm nginx.vip –o root $ORA_CRS_HOME/bin/crs_setperm nginx.vip –u user:oracle:r-x И проверяем работоспособность: $ORA_CRS_HOME/bin/crs_start nginx.vip $ORA_CRS_HOME/bin/crs_stat nginx.vip $ORA_CRS_HOME/bin/crs_relocate nginx.vip $ORA_CRS_HOME/bin/crs_stop nginx.vip |
Для регистрации nginx, как кластерного ресурса, подготовим скрипт для запуска, остановки и проверки статуса $ORA_CRS_HOME/crs/public/act_nginx.pl:
#!/usr/bin/perl if ($#ARGV != 0 ) { print "usage: start stop check required \n"; exit; } $command = $ARGV[0]; # start nginx if ($command eq "start") { system (" $NGINX_HOME/sbin/nginx"); } # stop nginx if ($command eq "stop") { system (" kill -TERM `cat $NGINX_HOME/logs/nginx.pid`"); } # check nginx if ($command eq "check") { check_nginx(); } sub check_nginx { my($check_master,$check_slave) = @_; $check_master = qx(ps -ae -o cmd | grep -w "nginx: master process $NGINX_HOME/sbin/nginx" | grep -v grep | wc -l); $check_slave = qx(ps -ae -o cmd | grep -w "nginx: worker process" | grep -v grep | wc -l); chomp($check_master); chomp($check_slave); if (($check_master eq 1) && ($check_slave ge $check_master)) { print "exit 0 \n"; exit 0; } else { print "exit 1 \n"; exit 1; } } |
Создадим и зарегистрируем nginx в Oracle Clusterware, указав подготовленный скрипт (-a $ORA_CRS_HOME/crs/public/act_nginx.pl), описание кластерного приложения (“NGINX”), название «родительского» ресурса, который должен быть в статусе ONLINE для успешного запуска nginx (-r nginx.vip), интервал проверки статуса (ci=5, в секундах), количество попыток перезапуска (ra=10):
$ORA_CRS_HOME/bin/crs_profile -create nginx -t application -d “NGINX” -r nginx.vip -a $ORA_CRS_HOME/crs/public/act_nginx.pl -o ci=5,ra=10 $ORA_CRS_HOME/bin/crs_register nginx $ORA_CRS_HOME/bin/crs_setperm nginx –o root $ORA_CRS_HOME/bin/crs_setperm nginx –u user:oracle:r-x |
Теперь можно запустить и проверить статус нашего комбинированного ресурса nginx.vip+ nginx:
$ORA_CRS_HOME/bin/crs_start nginx Attempting to start `nginx.vip` on member `node01` Start of `nginx.vip` on member ` node01` succeeded. Attempting to start `nginx` on member ` node01` Start of `nginx` on member ` node01` succeeded. $ORA_CRS_HOME/bin/crs_stat -t –v nginx application 0/10 0/0 ONLINE ONLINE node01 nginx.vip application 0/1 0/0 ONLINE ONLINE node01 |
И попробовать переместить ресурс на другой нод:
$ORA_CRS_HOME/bin/crs_relocate -f nginx Attempting to stop `nginx` on member ` node01` Stop of `nginx` on member ` node01` succeeded. Attempting to stop `nginx.vip` on member ` node01` Stop of `nginx.vip` on member ` node01` succeeded. Attempting to start `nginx.vip` on member ` node02` Start of `nginx.vip` on member ` node02` succeeded. Attempting to start `nginx` on member ` node02` Start of `nginx` on member ` node02` succeeded. $ORA_CRS_HOME/bin/crs_stat -t –v nginx application 0/10 0/0 ONLINE ONLINE node02 nginx.vip application 0/1 0/0 ONLINE ONLINE node02 |
Подготовим скрипт для кластерного ресурса HTTPD:
#!/usr/bin/perl if ($#ARGV != 0 ) { print "usage: start stop check required \n"; exit; } $command = $ARGV[0]; # start httpd if ($command eq "start") { system (" service httpd start"); } # stop httpd if ($command eq "stop") { system (" service httpd stop"); } # check httpd if ($command eq "check") { check_httpd(); } sub check_httpd { my($check_status) = @_; $check_status = qx(service httpd status); chomp($check_status); if ($check_status =~ m/^httpd \(pid .*\) is running...$/) { print "exit 0 \n"; exit 0; } else { print "exit 1 \n"; exit 1; } } |
Создадим и зарегистрируем ресурсы httpd1, httpd2,... на каждом ноде нашего кластера, точно указывая нод для запуска (-h) и «политику размещения» (-p placement_policy):
$ORA_CRS_HOME/bin/crs_profile -create httpd1 -t application -d "Apache httpd on Oracle Clusterware" -a $ORA_CRS_HOME/crs/public/act_httpd.pl -o ci=5,ra=60 -h node01 -p restricted $ORA_CRS_HOME/bin/crs_register httpd1 $ORA_CRS_HOME/bin/crs_setperm httpd1 -o root $ORA_CRS_HOME/bin/crs_setperm httpd1 -u user:oracle:r-x |
Скрипты для управления кластерным ресурсом «Виртуальный IP БД+файловая система БД+ MySQL» можно найти, например, у наших швейцарских товарищей
Для «файловой системы» $ORA_CRS_HOME/crs/public/action_mysql_fs.scr:
#!/bin/sh # Скрипт управления некластерной файловой системой БД SCRIPT=$0 ACTION=$1 # Action (start, stop or check) case $1 in 'start') /bin/mount /u01/www exit $? ;; 'stop') umount /u01/www exit $? ;; 'check') if [[ `/bin/mount|grep "/u01/www"|wc -c` -eq 0 ]] then exit 1 else exit 0 fi ;; *) echo "usage: $0 {start stop check}" ;; esac exit 0 |
Для « БД MySQL » - $ORA_CRS_HOME/crs/public/action_mysql_db.scr:
#!/bin/sh SCRIPT=$0 ACTION=$1 # Action (start, stop or check) case $1 in 'start') /etc/init.d/mysqld start > /dev/null 2>&1 exit $? ;; 'stop') /etc/init.d/mysqld stop > /dev/null 2>&1 exit $? ;; 'check') if [[ `mysqladmin -h mysql-vip.office.bitrix.ru ping 2> /dev/null` = "mysqld is alive" ]] then exit 0 else exit 1 fi ;; *) echo "usage: $0 {start stop check}" ;; esac exit 0 |
Теперь создадим и зарегистрируем элементы кластерного ресурса «Виртуальный IP БД+файловая система БД+ MySQL». Сначала VIP БД:
$ORA_CRS_HOME/bin/crs_profile -create mysql.vip -t application -a $ORA_CRS_HOME/bin/usrvip -o oi=eth0,ov=192.168.0.209,on=255.255.255.0 $ORA_CRS_HOME/bin/crs_register mysql.vip $ORA_CRS_HOME/bin/crs_setperm mysql.vip -o root $ORA_CRS_HOME/bin/crs_setperm mysql.vip -u user:oracle:r-x |
Процесс управления монтированием файловой системы БД:
$ORA_CRS_HOME/bin/crs_profile -create mysql.fs -t application -d "MySQL Filesystem" -r mysql.vip -a $ORA_CRS_HOME/crs/public/action_mysql_fs.scr -o ci=5,ra=60 $ORA_CRS_HOME/bin/crs_register mysql.fs $ORA_CRS_HOME/bin/crs_setperm mysql.fs -o root $ORA_CRS_HOME/bin/crs_setperm mysql.fs -u user:oracle:r-x |
Собственно БД MySQL:
$ORA_CRS_HOME/bin/crs_profile -create mysql.db -t application -d "Mysql Instance" -r "mysql.vip mysql.fs" -a $ORA_CRS_HOME/crs/public/action_mysql_db.scr -o ci=5,ra=60 $ORA_CRS_HOME/bin/crs_register mysql.db $ORA_CRS_HOME/bin/crs_setperm mysql.db -o root $ORA_CRS_HOME/bin/crs_setperm mysql.db -u user:oracle:r-x |
Важно отметить, что ресурс mysql.fs зависит от mysql.vip (-r mysql.vip), а mysql.db зависит и от mysql.vip и от mysql.fs (-r "mysql.vip mysql.fs"). После создания можно проверить, что Oracle Clusterware тщательно соблюдает зависимости между ресурсами – порядок запуска и остановки строго определён нами при создании:
$ crs_start mysql.db Attempting to start `mysql.vip` on member `node01` Start of `mysql.vip` on member ` node01` succeeded. Attempting to start `mysql.fs` on member ` node01` Start of `mysql.fs` on member ` node01` succeeded. Attempting to start `mysql.db` on member ` node01` Start of `mysql.db` on member ` node01` succeeded. $ crs_relocate -f mysql.db Attempting to stop `mysql.db` on member ` node01` Stop of `mysql.db` on member ` node01` succeeded. Attempting to stop `mysql.fs` on member ` node01` Stop of `mysql.fs` on member ` node01` succeeded. Attempting to stop `mysql.vip` on member ` node01` Stop of `mysql.vip` on member ` node01` succeeded. Attempting to start `mysql.vip` on member ` node02` Start of `mysql.vip` on member ` node02` succeeded. Attempting to start `mysql.fs` on member ` node02` Start of `mysql.fs` on member ` node02` succeeded. Attempting to start `mysql.db` on member ` node02` Start of `mysql.db` on member ` node02` succeeded. $ crs_stat -t -v Name Type R/RA F/FT Target State Host ---------------------------------------------------------------------- httpd1 application 0/60 0/0 ONLINE ONLINE node01 httpd2 application 0/60 0/0 ONLINE ONLINE node02 mysql.db application 0/60 0/0 ONLINE ONLINE node02 mysql.fs application 0/60 0/0 ONLINE ONLINE node02 mysql.vip application 0/1 0/0 ONLINE ONLINE node02 nginx application 0/10 0/0 ONLINE ONLINE node01 nginx.vip application 0/1 0/0 ONLINE ONLINE node01 |
Настраиваем nginx для
error_log /usr/local/nginx/logs/nginx.error_log info; events { worker_connections 1024; use epoll; } http { upstream myproject { server 192.168.0.201:8001; server 192.168.0.203:8003; } server { listen 192.168.0.208:80; server_name nginx-vip.office.bitrix.ru nginx-vip; location / { proxy_pass http://myproject; } } } |
Устанавливаем «Битрикс» и получаем производительный отказоустойчивый кластер приложений.
В случае конфигурации Oracle версии CMS «Битрикс» в качестве разделяемого дискового массива придётся использовать настоящий дисковый массив, т.к. для БД Oracle при использовании NFS требуется монтирование с опцией actimeo=0 (отключение кэширования атрибутов файлов и директорий на NFS клиенте), что значительно снижает производительность дисковых операций.
Процедура конфигурации отличается только в части установки Oracle и хорошо описана в