Проблематика
Итак, у нас есть коммерческий online-сервис, а наши клиенты — это компании, которые используют наш сервис 24x7. Наша задача, чтобы клиенты были счастливы и наши внутренние проблемы, связанные с отказом оборудования и ПО оставались для клиента максимально незамеченными. Клиенту вовсе не надо знать о том, что у нас сгорел RAID-контроллер, а системный администратор живет в Таиланде и не привык рано вставать.
Что мы хотели получить
Во первых, под online-сервисом будем понимать нечто более широкое, чем «информационный» WEB-сайт. Например, описываемое в данной статье решение было реализовано для проекта СМС-рассылок, где клиентом может быть банк, отправляющий СМС-оповещение с паролем платежа используя XML-API нашего сервиса.
Сервис включает в себя online-биллинг, данные в БД постоянно обновляются и должны оставаться сохранными в любых случаях. Доступность 24x7 очень важна.
Задачи, стоявшие перед нами:
- защититься от рисков, связанных с отказом оборудования
- защититься от рисков, связанных с отказом ПО (например, crash базы данных, «непонятное зависание» — все что угодно)
- защититься от рисков, связанных с пропаданием интернета и электричества в дата-центре
- после аварийных ситуаций сервис должен быть доступен клиентам по одному доменному имени 2kengu.ru
- хотим спать спокойно — чтобы в случае аварий все восстанавливалось само в общем временем простоя, необходимого для восстановления в пределах 15 минут
- хотим, чтобы решение стоило недорого, допустим, не более 8000 руб / мес без закупки дополнительного оборудования.
Стандартные простые варианты решения
В этой статье я не буду подробно расписывать все «за» и «против» таких решений как «хороший» RAID с массивом «качественных» HDD, сервер холодной замены, кластер и т.д. — это займет слишком много времени.
Остановлюсь лишь на паре моментов:
- 1. Мой пример со сгоревшим RAID'ом взят не с потолка. На моей практике действительно был случай, когда контроллер, установленный на сервере от солидного бренда из двух букв сгорел записав ошибку на все 5 подключенных к нему HDD. Так же может «сломаться» любая «железка» призванная обеспечивать безопасность — будь то роутер, Cisco, сторонний сервер-контроллер и что угодно еще — звено в системе безопасности снижает одни риски и добавляет другие.
- 2. Случается, что все старания по организации своей отказоустойчивой системы сводятся на нет проблемами, возникающими на стороне дата-центра. Просто пропадает электричество и от мира отрезается умный маршрутизатор, который должен принимать решение о вводе в строй резервного сервера и переключении IP-адресов.
Ваш покорный слуга не претендует на «открытие Америки» в поднимаемой теме. Решение которое мы реализовали для своего проекта СМС-рассылок основано на нескольких известных идеях.
Однако с учетом многолетнего опыта работы, в том числе и в крупных IT-компаниях — лидерах Российского рынка мобильных услуг могу констатировать, что такое (или аналогичное) элегантное и эффективное решение, гармонично сочетающее различные идеи — большущая редкость. Зачастую все пускается просто на самотек (авось сервер купили дорогой — не сломается, а через год купим новый). В лучшем случае организуются сервера «теплой» замены (с ручным заводом).
Рецепт. Все гениальное просто
- Берем 2 исходных сервера. Это могут быть VPS/VDS либо реальные сервера — не важно. В один момент времени сервис будет работать только на одном сервере, т.е. это не кластер.
- Размещаем сервера на различных площадках. Это очень важный пункт — как показывает практика, проблемы в дата-центре (выход из строя магистрального маршрутизатора, отключение электроэнергии и даже пожар) могут происходить чуть ли не чаще чем проблемы с вашим оборудованием и ПО.
- Устанавливаем на каждый из серверов бизнес-ПО, СУБД, синхронизируем базы данных. Настраиваем репликацию БД с одного сервера на другой. Настраиваем посуточную синхронизацию ПО и скриптов.
- Cинхронизируем сервера по времени.
Т.о. для каждого из серверов у нас могут быть два режима работы: master и slave.
В открытом доступе всегда находится только master. Slave в это время занимается только синхронизацией БД.
Самое интересное
Все решение построено на скриптах, написанных на bash. Скрипты на обоих серверах абсолютно одинаковые.
Нам потребуется 3-е звено (кроме наших двух серверов): DNS-хостинг от какого либо внушающего доверие поставщика.
Мы в своем проекте использовали DNS-хостинг Яндекс.
DNS-хостинг используется для двух вещей:
- хранение актуального IP-адреса master-сервера, на который должны переадресовываться клиенты обращающие к сервису по доменному имени
- хранение временной метки. Временная метка это просто строка (TXT-запись) содержащая известное вашим скриптам условное имя переменной и собственно значение — временную метку.
Яндекс предоставляет своим пользователям замечательную вещь — API для работы с DNS-записями. Использую этот API наши сервера могут читать и писать DNS-записи.
Логика работы сервера в режиме master
По cron'у, раз в 5 минут производятся следующие действия:
- производится проверка DNS-записи — совпадает ли текущий рабочий IP-адрес с адресом данной машины. Если совпадает, значит сервер все еще является мастером и продолжает функционировать по алгоритму мастера. Если IP-адрес изменился, значит данный проверяющий сервер уже не является мастером — он должен произвести процедуру перехода в slave.
- Записывается очередная временная метка — «сердцебиение» — в DNS TXT-запись записывается текущее время сервера.
Процедура переключения из режима MASTER в режим SLAVE
Процедура выполняется на master-сервере, когда он «понимает», что он больше не master. Это может произойти после того, как случилась авария и SLAVE поняв, что master-сервер недоступен сам становится master'ом. После того как авария устранена (дали электричество в дата-центре) поднимается «старый» master — наша задача, чтобы два сервера не работали в боевом master-режиме одновременно т.к. это может привести к рассинхронизации данных — для этого как только случается авария slave записывает в DNS свой собственный IP-адрес, что с одной стороны перенаправляет клиентов на новый IP, а с другой — является флагом для «старого» мастера, что он больше не мастер.
При переключении в slave бывший master выполняет следующие действия:
- останавливает WEB-сервер, выполняющий основные бизнес-функции
- запускает другой WEB-сервер, который работает как PROXY, перенаправляя все запросы от клиентов на другой — новый master-сервер. Такие запросы могут идти в случае, если у клиентов сервиса еще не обновились DNS-кеши и они все еще обращаются на «старый» IP-адрес.
- копирует полный дамп БД с нового master'а себе. Это необходимо сделать с одной стороны из-за того, что за время аварии (когда старый master был недоступен) накопилось уже много обновлений, а с другой — из-за того, что сама авария могла привести к повреждению БД.
- после копирования дампа запускает репликацию БД в режиме slave
- запускает логику работы сервера в режиме slave.
Логика работы сервера в режиме slave
По cron'у, раз в 5 минут производятся следующее действие:
- Производится проверка (только чтение) DNS TXT-записи, хранящей временную метку, которую записывает master-сервер. Если прочтенное в метке время отстает от времени данного сервера более чем на 10 минут — это сигнал, что с мастером что-то случилось и в этом случае slave запускает процедуру переключения в режим мастер. В противном случае slave продолжает «спать» очередные 5 минут
Процедура переключения из режима SLAVE в режим MASTER
Как уже было сказано, данная процедура запускается на slave-сервере, когда он «понимает», что не получил через общее DNS-хранилище очередную временную метку от master'a.
В этом случае нужно:
- Обновить DNS A-запись — записать свой IP адрес для перенаправления пользователей на новый сервер. (это делает только slave, переключающийся в master).
- Переключить СУБД на работу в master-режиме и подготовить дамп для того, чтобы его можно было загрузить на новый slave, когда он появится (см. процедуру переключения в slave).
- нужно остановить WEB-сервер, который выполняет функции PROXY переадресуя все запросы от клиентов на master-сервер.
- запустить WEB-сервер с основной бизнес логикой.
Слабые места
А что если сломается DNS-хостинг Яндекс?
Ну, во первых, мы верим в то, что Яндекс здорово заботится о стабильности своих сервисов, не жалеет на это денег (как мы) и сил. И как показывает практика, на самом деле — недоступность DNS-серверов Яндекс это большая редкость
И, во вторых, если DNS и недоступен какое то время то просто не надо делать ничего — пусть master продолжает работать в режиме master. Вероятность того, что авария Яндекс наложится на вашу аварию крайне низка.
Как быть с кешами DNS, перенаправляющими пользователей на «умерший» сервер.
Во первых, на Яндекс можно настроить время обновления кешей — установите их на минимальные значения.
Во вторых, можно оповестить технически подкованных клиентов о вашем резервном IP, чтобы они обращались к вашему сервису напрямую по IP в случае недоступности по доменному имени.
В случае когда оба сервера «живы» пользователи будут автоматически проксироваться на мастер.
В заключении
Естественно, кроме упомянутых слабых мест можно найти и еще.
Но тем не мене данная реализация уже зарекомендовала себя с самой лучшей стороны, не единожды избавив техников из 2кенгу от авральных работ по экстренному подъему сервиса.
Итого:
Затраты: 2 сервера (можно арендованных) — на ваш вкус + единоразовые работы по настройке скриптов.
Время неработоспособности сервиса в случае аварии: 10 минут на диагностику + 10 минут на переключение, итого 20 минут — в любое время дня и ночи — а вы, спокойно просыпаетесь утром, выпиваете чашечку кофе и узнаете обо всем разбирая письма.
Автор: Egorcheg