Как я делал отказоустойчивый веб-сервис

Предисловие


В этой статье я хотел рассказать о своем опыте построения отказоустойчивого Web-сервиса. Я разрабатывал внутреннюю систему управления предприятием на PHP+MySQL (корпоративный портал), и, так как почти вся жизнь предприятия зависит от работоспособности этой системы, вопросы отказоустойчивости приобретают большое значение. Вместе с тем предприятие небольшое, соответственно, позволить себе дорогое железо и технологии оно не может, да и простой системы в несколько часов для него тоже не смертелен. Поэтому я старался решить эту задачу с минимальными денежными вложениями и обходясь своими силами и небольшими знаниями в области администрирования.

Сразу хочу сказать, что специалистам, работающим с Heartbeat, DRBD, OCFS2, MySQL Cluster эта статья явно не будет интересна. Но если вы новичок в этом, деньги есть только на пару системников, а надежную систему построить хочется, то… читайте, что у меня получилось.

Задача


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

Общая схема решения


Итак, для создания своей системы я приобрел 2 недорогих системных блока (общая стоимость составила немного больше 30 т. руб.) следующей конфигурации:
  • Мат. плата Socket775 ASUS «P5Q-VM DO»
  • Процессор Intel «Core 2 Duo E8400»
  • ОЗУ DIMM DDR2 (6400) 2048Mb х 2
  • Жесткий диск 320Gb WD SATA-II 7200rpm 16Mb, Raid Edition
  • В главный сервер поставил 1 дополнительную сетевую карту, а в подчиненный – 2. Сетевые карты Intel Corporation 82541PI Gigabit Ethernet Controller.

Получился Главный сервер с 2-мя сетевыми интерфейсами и Подчиненный сервер с 3-мя сетевыми интерфейсами.

В качестве платформы, на которой работает корпоративный портал, я использую LAMP на базе Ubuntu Linux 8.04.4, которая работает в виде виртуальной машины VMWare. На самом деле я не большой специалист по настройке LAMP, поэтому доверяюсь профессионалам, и за основу беру готовую виртуальную машину 1С-Битрикс (http://www.1c-bitrix.ru/products/vmbitrix/).

Для того, чтобы запускать виртуальную машину на серверах, я остановился на варианте с установкой бесплатного гипервизора VMware vSphere HypervisorTM (ESXi) v. 4.1 на голое железо (bare metal), который и установил первым делом на оба сервера. Данный гипервизор представляет собой мини-операционную систему, функции которой сводятся к тому, что управлять виртуальными машинами. Установка прошла без проблем, однако, как я выяснил впоследствии, все-таки железо оказалось не совсем совместимо с ESXi. Хотя я проверял на этот предмет все комплектующие в найденных мной в Интернете white-листах (http://www.vm-help.com/esx40i/esx40_whitebox_HCL.php и http://ultimatewhitebox.com). Несовместимость выразилась в том, что ESXi не выводил полный спектр диагностической информации о состоянии серверного железа. Вроде не принципиально, но все-таки не очень хорошо.

Затем скопировал на оба сервера идентичные настроенные виртуальные машины с LAMP и своим корпоративным порталом. Затем настроил в ESXi сетевые интерфейсы. На Главном сервере (всего 2 LAN-интерфейса): 1 сетевой интерфейс настроил для доступа к ESXi и оба «привязал» к виртуальной машине. А на Подчиненном (всего 3 LAN-интерфейса): 1 интерфейс – для доступа к ESXi, а 2 других «привязал» к виртуальной машине.

Кабелем напрямую подключил оба сервера через сетевые интерфейсы, привязанные к виртуальным машинам. В виртуальных машинах назначил этим сетевым интерфейсам IP адреса (10.10.10.2 – для Главного и 10.10.10.3 – для Подчиненного) из подсети, отличной от сети LAN заказчика (172.20.15.0-255). Данное прямое соединение между серверами предназначено исключительно для «общения» виртуальных машин двух серверов между собой, а именно для репликации данных MySQL и синхронизации папок со скриптами.

Главный сервер через его второй интерфейс подключил в локальную сеть предприятия. Подчиненный сервер через интерфейс для работы с ESXi также подключил в локальную сеть, а третий его интерфейс, предназначенный для работы виртуальной машины, оставил не подключенным – в штатном режиме он не используется.

На Главном и Подчиненным серверах в виртуальных машинах назначил одинаковый IP для второго интерфейса, который «видит» виртуальная машина. В штатном режиме сетевой кабель подключен к этому интерфейсу на Главном сервере, а при его выходе из строя необходимо этот кабель переключить в соответствующий интерфейс Подчиненного сервера. Т.к. IP там задан одинаковый, никакие больше настройки не потребуются, и работа может быть продолжена.

Таким образом, получились следующие схемы работы системы в штатном режиме и при выходе из строя Главного сервера:
image

image

Теперь немного о нюансах.


Настроил стандартную репликацию в MySQL между Главным (сделал его мастером) и Подчиненным (сделал его рабом) серверами по кабелю, соединяющему сервера друг с другом. На эту тему есть много хороших материалов, описывать смысла не вижу. Хочу остановиться на некоторых моментах, которые, на мой взгляд, могут быть интересны.

Отслеживание состояния репликации MySQL.

При работе хотелось иметь возможность легко видеть, не прервалась ли репликация. Каждый раз заходить на подчиненный север через консоль в ESXi или через Главный сервер утомительно. Для решения этой задачи на подчиненный сервер я скопировал скрипт на PHP (checkslave.php), основная функция которого сводится к тому, чтобы получать статус репликации у МАСТЕРа и у РАБа и выводить их в виде таблицы. Главный сервер не может опрашивать подчиненный, т.к. в MySQL у него на это нет прав, права есть у подчиненного на доступ к главному, но не наоборот. Статус получается при выполнении команд:
SHOW SLAVE STATUS
и
SHOW MASTER STATUS

Т.к. пользователи имеют доступ только к Главному, на нем я в cron добавил команду:
wget --no-check-certificate 10.10.10.3/checkslave.php -O /var/www/checkslave.html, которая запрашивает с Подчиненного сервера checkslave.php и сохраняет его вывод в html-файл на Главном сервере. Соответственно можно смотреть на главном сервере в браузере этот файл и видеть, не ли проблем с репликацией.

Защита от разрыва репликации.

По мере работы столкнулся с тем, что репликация легко разрывалась при любом SQL-запросе на изменение, запущенном на подчиненном сервере. Это сразу приводило к созданию дублей в уникальный ключах и вообще к несогласованности данных. Достаточно было войти корпоративный портал на нем и репликация прерывалась. Чтобы сделать репликацию более надежной я добавил следующее. На подчиненном сервере я добавил два PHP-скрипта: один давал права на изменения пользователю MySQL, под которым работают скрипты корпоративного портала, а второй отнимал эти права с помощью команд SQL GRANT и REVOKE. Сами скрипты управления подключаются к MySQL под другим пользователем, под тем же, что работают скрипты опроса статуса МАСТЕРа и РАБа.

Затем я написал маленький скрипт, который проверяет, есть ли связь у Подчиненного сервера с Главным и соответственно запускает скрипт открытия/закрытия базы данных Подчиненного сервера на изменения. Скрипт запускается по расписанию каждые 5 минут. Соответственно через 5 минут после разрыва связи пользователи смогут работать с подчиненным сервером, а если связь не была разорвана, то подчиненный сервер будет оставаться закрытым от изменений:
#!/bin/bash

count=$(ping -c 8 10.10.10.2 | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
php -f /folder/slave_open.php
else
php -f /folder/slave_close.php
fi


Синхронизация скриптов.

Помимо синхронизации базы данных важно, чтобы PHP-скрипты и прочие рабочие файлы также менялись на подчиненном сервере при изменениях на Главном. Для решения этой задачи я на Подчиненном сервере по расписанию добавил команду:
rsync -avz 10.10.10.2:/var/www/ /var/www

Работа корпоративного портала с файлами.

Помимо PHP-скриптов корпоративный портал управляет файлами пользователей, которые также должны быть доступны и на Главном и на Подчиненном серверах. Чтобы сделать это возможным я вынес хранение этих файлов на отдельный файловый сервер предприятия под управлением Windows Server 2008. Там завел отдельную папку, написал скрипт, который на обеих виртуальных машинах проверяет, есть ли эта папка в примонтированных дисках, и если нет, монтирует ее.
flag=0
mnt_path='/folder'
mnt_test=`mount -t cifs`
flag=`expr match "$mnt_test" '.*folder.*'`
if [ "$flag" = "0" ]
then mount -t cifs -o username=user,password=pass,uid=bitrix,gid=bitrix,iocharset=utf8,codepage=866 //172.20.15.21/portal_folder /folder
fi


Далее все PHP-скрипты сохраняют файлы пользователей по определенной системе в этой примонтированной папке. Если работа переключается на подчиненный сервер, он сразу тоже монтирует эту папку себе, когда в него включают сетевой кабель и все продолжают работать. А если даже оба сервера выйдут из строя, можно будет напрямую воспользоваться файлами на файловом сервере.

Спасибо, если дочитали до конца!

Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 75

    +1
    Зачем делать master-slave репликацию, если Mysql поддерживает master-master?
      0
      У меня Слэйв выполняет роль «тени», идущей за Мастером. К Слейву пользователи даже не имеют доступа, пока не произойдет падение Мастера. Поэтому ему нет смысла тоже выполнять роль мастера.
        +2
        masta-master это самое плохое, что может быть. Хотя нет — самое плохое это «круговая» репликация с > чем 3 мастерами.
          +4
          Смотря как исползовать, если писать на все мастера, то нужно правильно готовить код и осознавать, что допустим insert into select from может по размному отработать. В любом случае это не подходит если, у вас какая-то CMS которую придется долго запиливать напильником, чтобы все было корректно.
          Я использую master-master только для того чтобы не заморачиваться с переключением slave/master при падении одного сервера. Просто перебрасываю ip между серверами.
            0
            Собственно большинство так и делает, но почему топикстартер решил нарушить эту практику, очень странно
              0
              Если нет необходимости в master-master, то зачем его делать ))) Можно потом потратить немало времени на разруливание split-brain.
            0
            почему master-master плохое решение?
          +1
          proxmox.com
            0
            Зачем, если есть ESXi?
              +7
              1) KVM и OpenVZ работают значительно быстрее чем гипервизор ESXi
              2) простой и понятный веб-интерфейс (у ESXi его нет вовсе)
              3) легкое построение кластера и миграция машин между нодами
              4) open-source
                –3
                2 и 4 несущественны: наш ехать а не шашечки.

                А вот на 1 и 3 пункты есть пруфы?
                  +6
                  «Ехать» можно на велосипеде, а можно на такси.
                  Пруфы есть, приложив минимум усилий ты их найдешь и без моей помощи.
                  –2
                  1. голословное утверждение или есть пруф?
                  2. у ESXi есть клиент (более чем приятный), а, кроме того, онлайная версия go.vmware.com (в облаке!)
                  3. никаких проблем у VmWare (правда, кажется, уже за деньги, а не в бесплатном варианте)
                  4. чем автору (пользователю, а не разрабу) поможет это дело?
                    +2
                    1) есть
                    2) круто
                    3) ага, за деньги
                    4) очень гибкая кастомизация решения под особенности конкретного заказчика, например
              +6
              один вопрос — как вы при таком конфиге(slave-master, односторонний rsync) возвращаете в работу «мастер» после его починки?
                0
                Бывшего master'а после починки делают slave, скорее всего. Правда, для этого на изначальном slave надо включить bin-log.
                  –1
                  По замыслу это делается вручную так:
                  1) восстанавливается виртуалка master (или откатываю на предыдущий safe-state или беру просто исходную)
                  2) актуализирую ее (разворачиваю последний дамп базы, взятый со slave, заливаю последние версии скриптов)
                  3) включаю master в сеть, slave соответственно отключается от сети, подключаю обратно кабель репликации

                  slave с master местами никогда не меняю. У них есть ряд специфических настроек, они не вполне взаимозаменяемые. Slave нужен, чтобы временно взять работу на себя, чтобы можно было спокойно восстановить master и вернуть все на круги своя.

                  Да, это восстановление довольно трудоемое (ну 1-2 часа, максимум занимает), но и виртуалка падает крайне редко (стучу по дереву). На самом деле из моего опыта в двух организациях, такая виртуалка, работающая внутри сети годами не дает никаких сбоев.
                  +3
                  о опции read-only на слейве автор не слышал.
                    0
                    Если можно поподробнее. Разве не получится, что если я переведу slave в режим read-only, он перестанет у себя выполнять запросы на изменения, приходящие с master и репликация не будет происходить?

                    Я же на slave имею 2 пользователя MySQL — под одним идет репликация, под другим работают скрипты портала. И я запрещаю изменения тому пользователю, под которым работают скрипты портала, до того момента, пока не прервется репликация и slave не начнет обслуживать пользователей.
                      0
                      dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_read_only

                      Ставишь в my.cnf
                      read_only
                      И апдейты будут накатываться только те что пришли с мастер-сервера по препликации и только от пользователей с Super_priv
                        0
                        Действительно автор не слышал про такую опцию… :)

                        Но тогда будет другая проблема — убрать эту опцию, когда slave начинает обслуживать пользователей? Придется писать скрипт, который будет редактировать my.cnf и перезапускать mysql?
                          +1
                          ну какбы есть несколько вариантов.
                          1. Скрипт может редактировать файл и дергать mysql.
                          2. Можно задать опцию с помощью
                          mysql -e «set global variable read_only=0»
                          3. Использовать опцию read_only с командной строки.
                          Когда нужно запускать mysql c --read-only а когда не нужно — без нее.
                    +1
                    А у меня вопрос про дубли в уникальных ключах, не совсем понял о чем речь и каким образом такие дубли вообще могут создаться, если поле уникальное?
                      0
                      Думаю там 2 варианта. Или оно как бы уникальное или как бы дубли )
                        0
                        Это происходит если войти в портал на slave, в его базу производится, например, запрос INSERT. Соответственно при этом для вставляемой записи в таблице генерится новый ID. При этом на master запускается другой INSERT. И когда в дальнейшем с master приходит этот запрос уже по каналу репликации, то оказывается, что у slave уже есть запись с таким ID и это приводит к разрыву репликации.
                        +19
                        image
                      • UFO just landed and posted this here
                          +1
                          тогда что мешало арендовать один дедик в датацентре

                          Зачем внутрикорпоративный портал размещать вовне?
                          Автор пишет, что вся жизнь предприятия зависит от работоспособности этой системы. А вдруг или интернет не проплатят, или сбой у провайдера — и всё, доступа к датацентру нету. Надёжность системы уменьшена.
                            –2
                            Я думаю запустив сервер на hetzner ничего страшного не случится… это как хранить деньги в швейцарском банке. А экономия на лицо…
                              +1
                              ХАХА! Хецнер с его десктопным железом ну никак не катит быть аналогией с банком )
                              • UFO just landed and posted this here
                                • UFO just landed and posted this here
                                    0
                                    ???
                                    • UFO just landed and posted this here
                                –3
                                А интернет упадет — дык он обычно падает вместе с локальным=) Непроплатить с тем же успехом можно и свет…
                                  0
                                  Ага. Только электричество за неуплату отключат не раньше чем чрез месяц (и это при плохом раскладе), и то на мозги накапают так, что не заплатить не возможно. А интернет легко могут рубануть первого числа очередного месяца практически без предупреждения (это от провайдера зависит). И, простите, вместе локальным чем падает обычно интернет?
                                  +2
                                  что будет с надежностью системы при пожаре в офисе?
                                    +1
                                    В этом случае, надежность системы не важна, так как все равно во время пожара никто не работает, все бегают по кругу, машут руками, некоторые снимают на мобилы.
                                  • UFO just landed and posted this here
                                    +1
                                    Я делал это год назад, а убунту 8.04.4 вышла в январе 2010, не такая уже древняя на мой взгляд.

                                    Насчет 100$ фрилансеру… Мне это не кажется хорошим решением. Я больше доверяю специалистам 1С-Битрикс (не сочтите за рекламу). Они делают качественно настроенную виртуалку с LAMP.

                                    Вариант с размещением на внешнем хостинге рассматривал. Но там есть минусы: зависимость от Интернета, сложности с монтированием файлового сервера к виртуалке с порталом и вообще с интеграцией в инфраструктуру локальной сети предприятия. Вариант с размещением серверов внутри показался предпочтительнее. Но я не исключаю, что в следующих проектах попробую вариант с внешним хостингом портала (он, безусловно, имеет и свои плюсы).
                                    • UFO just landed and posted this here
                                        0
                                        В январе там вышла версия только с критическими обновлениями, а все остальные внутренности древние. И зачем, спрашивается, если 10.04 год назад уже была?
                                      • UFO just landed and posted this here
                                        • UFO just landed and posted this here
                                        0
                                        > Ubuntu Linux 8.04.4
                                        o_O
                                          0
                                          Да, да я тоже удивился. Почему не 10.04?
                                          +32
                                          >>LAMP на базе Ubuntu Linux
                                          image

                                          >>8.04.4
                                          image

                                          >>которая работает в виде виртуальной машины VMWare
                                          image
                                            0
                                            Признатся, тоже не понял зачем поднималась вирт машина и почему такая древняя убунта)
                                              +1
                                              Пока grammar-nazi не прибежали, «признаться»* — опечатался
                                                –2
                                                Убунта не такая уж древняя, она выпущена 28 января 2010 года, а я собирал эту систему год назад. Сейчас уже, конечно, есть более новые версии.

                                                А виртуалка — удобная вещь. Ее можно легко копировать, запоминать состояния и откатывать в случае проблем. Можно в случае чего запускать на любом компьютере и под разными операционными системами.
                                                  0
                                                  Понятно, спасибо за разъяснения!
                                                +1
                                                «готовую виртуальную машину 1С-Битрикс» забыли :)
                                                +3
                                                А если сервер упадет в 2 ночи? А если Вас утром после вчерашнего тошнит-с и приехать выдернуть шнур выдавить стекло нет никаких? Что-то не вяжется отказоустойчивость с выдергиванием шнура.
                                                  +2
                                                  я вообще не понял, зачем городить велосипеды с кабелями :)
                                                    0
                                                    Самое смешное, что файлы пользователей хранятся на 100% надежном сервере предприятия в одном экземпляре. Возникает вопрос — а почему сайт там сразу не хранить?
                                                      +1
                                                      100% надежном… в одном экземпляре О_О
                                                        0
                                                        На файловом сервере помимо файлов портала хранятся и другие файлы. Там делается регулярный бекап, а может он даже на RAID-массиве, это уже не входит в мою компетенцию в этой организации.

                                                        Надежность системы в целом повышается благодаря децентрализации ее частей.
                                                      0
                                                      Шнуры легко могут переткнуть обученные ответственные сисадмины на местах. Это не проблема.
                                                      +5
                                                      Сразу хочу сказать, что специалистам, работающим с Heartbeat, DRBD, OCFS2, MySQL Cluster эта статья явно не будет интересна. Но если вы новичок в этом, деньги есть только на пару системников, а надежную систему построить хочется, то…

                                                      … то лучше все-таки почитайте про DRBD, Heartbeat и иже с ними, и не городите странности.
                                                        +1
                                                        полностью поддерживаю. Те же два сервака, на которые так грустно потратился ТС и плюс ноду, для которой хватит и старого железа из загашника, чтобы она без проблем следила за жизнью и смертю серваков. У меня в кач-ве ноды летал ВДС на xen'е с 128мб памяти
                                                          0
                                                          С этим я согласен, но просто реалии таковы, что поднимать полноценный кластер с DRBD, Heartbeat уже не укладывалось в бюджет проекта. У меня самого на изучение ушло бы много времени и сил, меня хватило на то, на что хватило. А нанимать админа для создания кластера уже не входило в бюджет ну никак.

                                                          Но я все равно пробовал найти людей, умеющих делать кластеры DRBD, Heartbeat на сайтах фриланса. Почему-то все говорили, что опыта такого нет. Даже до обсуждения вознаграждения не доходило.
                                                            +1
                                                            силы на что? Набрать в гугле «настройка drbd+heartbeat» и нажать на первую или вторую ссылку, где русским языком по шагам расписано понятней колобка? Скажу честно — следую инструкциям, достаточно на все про все было бы нескольких минут, не больше
                                                        +1
                                                        А если пожар?
                                                          0
                                                          Безусловно, такой подход не гарантирует физической сохранности носителей информации, а следовательно и данных.
                                                          Но подозреваю что автор еще и бэкапит куда-то все это дело, чтобы можно было восстановить в таких случаях. Т.к. вероятность реализации физической угрозы не велика, то я думаю можно позволить себе потратить больше времени на восстановление работоспособности системы, в случае чего.
                                                          +2
                                                          я надеюсь, что два сервера хотя бы стоят в разных углах офиса, так как если ворвется недавно уволенный сотрудник с гранатой в руке и побежит в серверную, то надежность системы сильно пострадает.
                                                          • UFO just landed and posted this here
                                                              0
                                                              >>А как переключить обратно? Потухший бывший мастер содержит неактуальную версию БД. Его теперь надо запускать в режиме слейва, опять сливать на него дамп и прописывать позицию бинари лог руками…

                                                              Делается скриптом у меня за минуту.
                                                              +1
                                                              Эта задача решается так:

                                                              1) на каждом сервере настроить keepalived (который будет перевешивать ip и при необходимости перезапускать сервисы)
                                                              2) mysql репликацию в режиме master-master (+auto_increment_offset) на обоих серверах (позволит писать на любой сервер).
                                                              3) GlusterFS в режиме distributed+replicated для хранения файлов на обоих серверах (отказоустойчивое хранилище).
                                                              • UFO just landed and posted this here
                                                                  0
                                                                  У DRBD есть 1 минус — если разъединить ноды и создать на каждой из них по новому файлу(с разными именами), при восстановлении связи всё ломается и приходится руками разрешать «конфликт». Причем нельзя выбрать вариант, когда останутся оба файла. Да, это можно автоматизировать, но суть остаётся прежней — надо выбрать с какой ноды синхронизироваться, а на какой затирать изменения.
                                                                  В GlusterFS такого косяка нет.
                                                                0
                                                                Автор, приходилось ли проверять эту схему «в бою»? Т. е. были ли сбои первого сервера?
                                                                  0
                                                                  В бою пока не довелось. Уже 1 год первый сервер работает без сбоев. А при тестировании проверял, конечно.

                                                                  В другой фирме у меня аналогичная виртуалка работает уже много лет (года 3, как минимум) без сбоев…
                                                                  0
                                                                  DRBD & HA и не надо никаких образов, ESXi, третьего интерфейса, ручного переключения.
                                                                  Это все просто будет работать годами.

                                                                  Only users with full accounts can post comments. Log in, please.