Не так давно я писал о волейбольный сервис , теперь пришло время описать это с технической точки зрения.
Возможно, общественное сознание найдет недостатки в архитектуре и подтолкнет к лучшим решениям.
Краткое описание функционала:
- пользователь загружает видео волейбольного матча
- один умный алгоритм распознает мяч в кадрах
- другой умный алгоритм выделяет ничьи
- розыгрыши компилируются в отдельные видеофайлы
- файлы с розыгрышами собраны в дайджест всей игры
- все видео загружаются в облако
- пользователи смотрят/скачивают/делятся клипами с самыми крутыми розыгрышами
Теперь как все это работает.
Технологии
Все написано на питоне, веб-сервис — Django/Gunicorn. OpenCV и FFMpeg активно используются.База данных — Постгрес.
Кэш и очередь — Redis.
Альфа
Самая первая версия имела 3 компонента:- Передний — Веб-сервис (Django), с которым взаимодействуют конечные пользователи
- Видеопроцесс (Впрок) — Ядро алгоритма python + opencv, содержащее все алгоритмы отслеживания шаров и логику разрезания на ничью.
- Клипер — Сервис генерации видео на основе вывода Vproc с использованием ffmpeg.
Разработка велась локально, я установил Ubuntu на домашний рабочий стол, а на нем микрок8с и получил небольшой кластер Kubernetes. Тут я столкнулся с тем, что кадры, которые видит opencv, на самом деле не совпадают со временем, которое видит ffmpeg из-за особенностей кодеков, поэтому вычислить время в исходном файле по номеру кадра оказалось невозможно.
Из-за этого пришлось сохранять кадры, что сильно замедлило процесс и потребовало дальнейших архитектурных изменений.
Параллельная обработка
Как уже упоминалось, время обработки в 3 раза превышает время игры.Профилировщик показал, что большая часть времени тратится на запись кадров на диск, а сам парсинг кадров происходит примерно в два раза быстрее.
Логично провести параллель этих двух работ. По первоначальной задумке, пока vproc разбирает кадры через opencv, ffmpeg одновременно записывает всё на диск, а клиппер собирает из них видео.
Но с ffmpeg было две проблемы:
- Кадры из ffmpeg не идентичны кадрам из opencv (это не всегда так, в зависимости от кодека видеофайла)
- Количество кадров в записи может быть слишком большим — например, час видео с хорошим fps — это около 200К файлов, что очень много для одного каталога, даже если это ext4. Разделил его на подкаталоги и потом объединил при компоновке видео - не хотелось усложнять
Как только они появляются, фреймер загружает необходимые кадры в отдельный каталог.
Дополнительным преимуществом является то, что не экспортируется ни один лишний кадр.
Мелочь, но всё же.
Производительность (на основе 10-минутного тестового видео): Был:
Завершенный файл с id=73, для игры=test, кадров=36718, fps=50, длительности=600 за 1677 сек.Стал:
Идентификатор завершенного файла=83, для игры=тест, кадров=36718, кадров в секунду=50, длительности=600 за 523 секунды + время кадра 303Дважды выиграть – очень хорошо.
Если писать в несколько тем, наверное, можно выжать немного больше.
Если хранить кадры в памяти и генерировать из них видео через API, то, скорее всего, можно существенно ускориться.
Цифровой океан
Потом я начал выбирать хостинг.Понятно, что основные варианты — GKE, AWS, Azure, но многие авторы небольших проектов жалуются на непрозрачное ценообразование и, как следствие, довольно большие счета.
Основная проблема здесь — цена на исходящий трафик, она составляет около $100/Тб, а поскольку речь идет о раздаче видео, вероятность серьёзного удара очень мала.
Тогда я решил присмотреться ко второму эшелону — Digital Ocean, Linode, Heroku. На самом деле Kubernetes-as-service уже не такая уж редкость, но многие варианты выглядят неудобными для пользователя.
Digital Ocean мне понравился больше всего, потому что:
- Управляемый Kubernetes
- Управляемый Postgres
- Хранилище S3 с бесплатным(!) CDN + 1 ТБ/мес.
- Частный реестр докеров
- Все операции можно выполнять через API
- Дата-центры по всему миру
Так в архитектуре появился четвертый компонент — Pusher.
Однако серьезным недостатком оказался невозможность монтировать один и тот же диск на нескольких машинах одновременно .
ДЕЛАЙ сам предложения в таких случаях используйте NFS через выделенный контейнер, но я пока решил не заморачиваться, потому что, как уже говорилось выше, назревает специальное решение для видеокадров, и если у вас уже есть отдельный контейнер, то и для него.
Однако отсутствие общего диска сильно повлияло на архитектуру.
Если передачу загруженного файла можно было осуществить через S3, то пересылка сотен тысяч кадров туда и обратно не представлялась блестящим вариантом.
В результате нам пришлось привязывать все этапы обработки конкретного видео к одному узлу, что естественно снижало общую масштабируемость системы.
Журналы и метрики
Запустив кластер в облаке, я начал искать решение для сбора логов и метрик.Я не хотел возиться с хостингом всего этого самостоятельно, поэтому целью был бесплатный уровень в каком-нибудь облаке.
Не у всех такое есть: Модный Grafana хочет $50 в месяц, вышедший из моды Elastic — $16, Splunk даже прямо не говорит. Но вдруг выяснилось, что New Relic, также известная своими негуманными ценами, теперь бесплатно предоставляет первые 100G в месяц.
видео
Казалось вполне естественным решением разделить кластер на два пула узлов:- фронт — на котором крутятся веб-серверы
- vproc — где обрабатывается видео
Во-первых, обработка видео требует серьезных ресурсов (= денег), во-вторых, его приходится обрабатывать нечасто (особенно на начальном этапе проекта).
Поэтому я хочу включить обработку только для обработки видео (время обработки в 3 раза превышает продолжительность действия).
Kubernetes формально поддерживает автомасштабирование 0, но как именно это реализовано, мне не удалось найти, но я нашел.
Это обсуждение переполнения стека .
В результате мне пришлось добавить в передний пул еще один под, единственная задача которого — иногда смотреть в postgres и включать/выключать пул обработки в зависимости от того, что было в базе данных.
DigitalOcean имеет неофициальный клиент для Python , но он давно не обновлялся, а API Kubernetes там вообще не присутствует. Я сделал это на колене клиент для меня это охватывает процентов десять возможностей, но вдруг кому-то понадобится для начала.
В итоге диаграмма выросла вот так:
DevOps
Несмотря на большое разнообразие инструментов CI/CD, не было ничего удобнее в разработке, чем Jenkins. А действия Github идеально подходили для управления DigitalOcean.Ссылки
- Услуга, о которой идет речь в этой статье
- DigitalOcean Кубернетес
- DigitalOcean API для управления кластером
- Уровень бесплатного пользования «Новая реликвия»
-
Шпионское По – Бич Нового Тысячелетия
19 Oct, 24 -
Не Повторяйся
19 Oct, 24 -
Совмещение Изучения Английского С Досугом
19 Oct, 24 -
Уязвимость Нулевого Дня В Adobe Reader X/Xi
19 Oct, 24 -
Спрингпад Всё...
19 Oct, 24 -
Sony-Ericsson: Стереогарнитура С Gps
19 Oct, 24