Все чаще бизнесу приходится резервировать текущую инфраструктуру, чтобы повысить свою отказоустойчивость и качество предоставляемых услуг. Как правило, резервируется целая машина с нужным сервисом или кластер по схеме N+N. Но, что, если серверов много, а данные, которые нужны для полного восстановления сервиса, весят меньше мегабайта?
В этой статье мы рассмотрим базовую механику резервирования хостов по схеме N+k, где N — количество основных серверов, k — резервных.
Если вы решите создать свою сигнальную среду, эта статья для вас.
Предметная область
Сейчас я работаю на проекте, который специализируется на транскодировании и потоковой передаче видео в реальном времени. Движок поставляется в виде серверного ПО по лицензии. Имеет поддержку популярных протоколов передачи видео данных и большой набор различных решений для бизнеса - шифрование видеопотоков, наложение логотипов, blackout (перекрытие эфира), поддержку меток (SCTE, DTMF). К основной части ПО отдельно поставляется UI. Это весомый плюс, который сыграет в последствии нам на руку.
Известно, что ПО приобретают как единичными экземплярами, так и разворачивают на целые кластеры. Те, кому позволяют возможности и инфляция приобретают сразу дублирующие лицензии и заводят зеркальные серверы (схема резервирования N+N). Другие, скорее, отказываются полностью от резервирования. И таких преимущественно больше…
Учитывая стабильность работы кодирующего ПО, статистику выхода из кластера (недоступности) машин и данные, которые нужны для восстановления (а их действительно меньше 1 МБ), мы с командой решили подготовить сервис, позволяющий применять клиентам схему резервирования N+k.
Рецепт транскодирования
Собственно рецепт транскодирования в реальном времени сводится к четырем основным компонентам:
где кодировать (сервер),
что кодировать (источник сигнала). Чаще всего: UDP, MPEGTS-over-IP, SRT, RTMP,
по каким правилам (конфигурационный файл),
что получить на выходе (результирующий поток(и)). Чаще всего HLS, DASH, SRT, RTMP, UDP, MPEGTS-over-IP.
Тогда для восстановления системы потребуются:
источник сигнала,
конфигурационный файл,
в частных случаях периодически требуемые файлы для работы сервиса (видео файлы, изображения, расписание),
и, собственно, «живой» сервер с работающим ПО.
Кодирующее ПО включает 3 части:
streambuilder — главная часть, транскодирует потоки,
streambuilder-api — программный интерфейс, позволяющий управлять транскодером по сети, всегда ставится с основной частью.
streambuilder-ui — визуальная часть проекта или интерфейс управления пользователя. Позволяет удобно создавать конфигурации, просматривать статус сервисов и т.д. Идет как дополнительная часть, нужно устанавливать отдельно.
UI необязательно ставить вместе с основной частью, можно использовать вообще любую машину, имеющую сетевой доступ к серверам с API. Это дало ключевой вектор в решении текущей задачи. Именно к UI мы и решили добавить логику проверки серверов на доступность, сохранение бекапов конфигураций и перенос сервисов с одного хоста на другой.
Создаем логику бекапа сервисов
По практике проекта есть два типа пользователей — рядовые и продвинутые. Последние нередко управляют сервисами транскодирования напрямую через рутовую консоль в обход web-панели администратора.
Отсюда возникает вопрос: как синхронизировать такие конфигурации?
Решением стало создать периодическую задачу сравнения конфигураций. Как это работает: при создании конфигурации сервиса (канала/сhannel) мы добавляем его в базу данных. После чего, раз во время запрашиваем у хоста сравнение конфигураций.
Постоянная передача конфигураций по сети не является оптимальным решением. Вместо этого мы будем отправлять хосту название сервиса и хеш конфигурации. Если проверка проходит успешно, API возвращает «True». В случае несоответствия хешей, API возвращает отрицательный ответ, а также конфигурацию и её хеш, которые мы сохраняем в базе данных. Это позволяет быстро перенести конфигурацию на резервный хост и запустить сервис там, если основной хост становится недоступным.
Хорошо, мы успешно создали резервные копии сервисов, но как узнать, что хост действительно вышел из строя, а не просто возникла одноразовая сетевая ошибка?
Настраиваем проверки доступности серверов
На текущем этапе мы остановились на проверках двух типов: доступность API и доступность хоста.
Основной и первой работает проверка доступности API раз в . Если проверка не проходит, хосту назначается статус «обрати внимание». Здесь же запускается дополнительная вторая проверка, которая срабатывает раз, с периодом в сек. Она проверяет доступность api и дополнительно доступность всего хоста путём ping запроса.
Такой способ позволяет уменьшить вероятность ошибочного срабатывания автоматического переноса сервисов на резервный хост.
Мы вынесли параметры количества запросов и ожидания ответа в интерфейс ПО и сделали их настраиваемыми, чтобы администраторы могли задавать параметры проверок для своей конкретной сети.
Забегая вперед, за подбором настроек нам удалось полностью восстановить кластер за менее 10 секунд.
Сломался, несите следующего
После срабатывания системы определения доступности хоста мы получаем сигнал о том, что хост недоступен. Значит, пора переносить сервисы на резервный сервер.
В UI кластера администратору необходимо заранее пометить и держать в актуальном состоянии серверы с пометкой «резервный». Сервер нельзя назначить резервным, если на нем уже запущены сервисы streambuilder. Это сделано с целью предупредить проблемы с производительностью и уникальностью имён сервисов.
После получения сигнала о недоступности хоста, автоматика берет все сервисы хоста и запускает их на резервном сервере. При этом резервных серверов может быть несколько, по-умолчанию система сама определяет сервер.
Здесь следует отметить, что серверы должны иметь примерно одинаковую производительность. Возможно, в будущем мы разработаем бенчмарк для сравнения производительности хостов. А пока практика показывает, что эта задача не является актуальной, поскольку обычно используется однотипное оборудование.
Что делать, если основной хост стал доступен
Есть несколько причин, по которым сервер может быстро пропадать из сети, а затем возвращаться (проблемы с сетевым подключением, проблемы с электропитанием и тд).
Мы решили, что возвращать автоматикой обратно сервисы это дополнительные потери стабильной отдачи выходного потока. С этой целью, как только сервер снова становится доступным, запускается задача удаления сервисов streambuilder. Что позволяет поддерживать стабильность и надежность в потоке выходных данных, предотвращая несанкционированное вещание с двух серверов одновременно и обеспечивая качественную доставку контента получателям.
Статус резервного сервера переходит в основной, резервный — на обслуживание администратору. Пользователь может, по необходимости, перенести сервисы на этот хост через web-интерфейс или назначить роль серверу «резервный».
Источник и выходящие потоки — как сообщить, что мы переехали
Задача получить входящий сигнал решается подпиской резервного сервиса на мультикаст, если мы используем UDP. С выходом в UDP проблем тоже нет, отправляем вещать выход в мультикаст.
При использовании выходов с манифестами HLS или DASH всё немного сложнее — нужен DNS сервер. DNS должен иметь конечную точку, которая даёт возможность быстро изменить адрес сервера для конкретного имени, при смене сервера на котором работает сервис. Логика такая: клиент получает ссылку на плейлист (test_channel_host.com/live.m3u8), которая ведёт к серверу, где изначально находится сервис. При смене расположения канала система резервирования сигнализирует DNS серверу о том, что теперь выход с канала нужно забирать с другого сервера. Приняв запрос, DNS меняет записи в таблице на новые (например test_channel_host.com = 192.168.100.20 меняется на 192.168.100.52), что позволяет клиенту не менять адрес источника при смене сервера. Этот функционал сейчас находится в разработке.
Файлы, которые используются при кодировании потоков
Часто сервисы кодирования используют медиа файлы (видео, графика, расписание) — это могут быть сценарии, когда при кодировании накладывается логотип на видеопоток или, например, по расписанию добавляются возрастные метки на кадр видео или метки о вреде курения.
Для таких файлов предлагается использовать сетевое хранилище — сервис при запуске загружает нужные ему файлы по ссылкам указанным в конфигурации, что играет нам на руку и избавляет от необходимости:
перебрасывать медиа файлы по сети между хостами,
обновлять пути хранения файлов в конфигурациях.
Тесты и выводы
В итоге, мы имеем стабильную систему, которая при отказе работы основных хостов, позволяет максимально быстро восстановить работу сервисов транскодирования.
Максимальное время вычисляется как , где
период основной проверки, по умолчанию 5 секунд, — количество доп. проверок, умноженное на время задержки между попытками, по умолчанию 5 секунд и 5 проверок,
время на перенос каналов. Зависит от производительности хоста и сети, в среднем 10 сервисов в секунду, здесь считаем 10 сервисов.
— среднее время запуска сервиса, зависит от того, когда придёт ключевой кадр.
Получается 5+25+1+10 = 31 секунда, если использовать стандартные настройки, но это время можно уменьшить изменив настройки под конкретную сеть.
Минимально рекомендованные: позволяют сократить время до максимум 19 секунд.
Не рекомендуется делать эти значения меньше, так как, чем меньше эти настройки, тем более вероятна ситуация необоснованного перемещения сервисов. Например, в ситуации, когда моргнула сеть.
Конечно же, реализованная схема проигрывает по скорости переключения между хостами по схеме N+N, но учитывая стабильность системы, схема N+k может сильно сократить затраты на используемые серверные мощности и оптимизировать бюджет.