avatarcommunity
EntHub2 дня назад

Как устроена медиаконвертация на хабе: от боли к микросервисной архитектуре

Морская задала вопрос в личку: почему видео сжимаются, уменьшается количество кадров и как вообще работает медиаконвертация. Пока объяснял, понял, что получился целый лонг, поэтому делюсь им с вами тоже. Кстати, я немного улучшил качество в конвертере для видео и теперь оно должно стать лучше(но это не точно).

image

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

***

Когда речь заходит о работе с медиа на сайте, кажется, что все просто: загрузил файл и он отобразился. Но на деле за этим стоит целая цепочка сервисов, оптимизаций и решений, которые мы принимали не один вечер. Расскажу, как мы выстраивали систему медиаконвертации на хабе: от первых проблем до текущей архитектуры.

***

На первый взгляд немного. В момент нашего неожиданного роста весной прошлого года, когда за день пользователи загрузили 25 ГБ медиа (без всякой оптимизации), цифры не выглядели катастрофическими, но пугали. После внедрения конвертации и оптимизации медиаконтент стал занимать куда меньше места: на текущий момент мы съедаем всего около 220 ГБ.

Не так уж и много. 
Не так уж и много. 
***

Главным врагом оказались тяжелые файлы.

  • Картинки: мы начали конвертировать все в WebP. Этот формат при одинаковом разрешении дает меньший размер файла. В итоге большинство изображений на хабе весят буквально десятки килобайт.
  • Видео: используем FFmpeg для конвертации в WebM. Это прогрессивный формат, поддерживаемый всеми браузерами и идеально подходящий нам по соотношению качества и размера.

На бумаге решение простое, но на практике начались новые трудности.

***

Когда весь хаб и медиаконвертер работали на большом сервере с последним AMD EPYC(48c/96t), проблем не было заметно. Но стоило затянуть пояса и переехать на сервера в РФ - стало заметно как хаб убивает сам себя, сразу не было понятно почему, ведь нагрузка на веб-сервер небольшая а процессор все равно улетает в 100%, немного покопав оказалось что конвертация видео слишком прожорлива. Каждый ролик отнимал 4-5 ядер процессора на минуту, и если в этот момент совпадала нагрузка от самого хаба, CPU улетал в 100% на 5-7 минут. За это время сервисы веб-сервера пытались как-то реанимировать сами себя, и в итоге падали из-за недостатка процессора.

Решение оказалось очевидным: разнести сервисы по разным серверам.

  • Хаб - на одной машине (6 CPU / 16 GB RAM).
  • Конвертер - на другой (4 CPU / 8 GB RAM).

Теперь они общаются по API, и хабу стало намного легче.

***

Все медиа у нас хранятся в S3, и хаб тянет их напрямую. В результате:

  • Ежемесячный расход трафика доходил до 7-8 ТБ.
  • Загрузка страниц заметно тормозила из-за тяжелых файлов.

Выходом стало внедрение кэширующего сервера. Мы построили цепочку на основе Varnish + Nginx, добавили Python-скрипт для автоподписи SSL (так как open-source версия Varnish не поддерживает HTTPS), и в итоге ускорили отдачу медиа в разы.

Вроде как неплохая стата(или нет)
Вроде как неплохая стата(или нет)
***

Все устроено примерно так:

  1. Пользователь прикрепляет медиафайл.
  2. Файл уходит в конвертер.
  3. Отконвертированный файл сохраняется в хранилище, оригинал временно лежит в темпах.
  4. При показе файла на хабе он кэшируется.
  5. После публикации уже оптимизированный файл отдается из кэша, а не напрямую из S3.

Результат: страница грузится быстрее, трафик уменьшается, серверу проще.

***

Помимо основной схемы, есть еще несколько фишек:

  • Очереди и автоскейлинг: если загружается сразу несколько видео или десятки картинок, конвертеры автоматически масштабируются и потом схлопываются.
  • *Проверка на уникальность: когда одна и та же картинка загружается повторно Мы ее сохраним, но повторно конвертировать не будем.
  • Гибкость в очередях: система балансирует нагрузку так, чтобы пользователи не ждали слишком долго.

*Вопрос о повторном хранении файла очень сложный ибо если удалится оригинал - то он удалится отовсюду, поэтому проще хранить оптимизированные копии. На текущем этапе по крайней мере.

***

На словах все кажется простым, на деле - мы(я, лол, зачем я о себе в третьем лице говорю всегда) потратили немало времени на отладку этой архитектуры. Сейчас она выглядит так:

  • Docker - для всего окружения.
  • Медиа-прокси: Varnish + Nginx + Python (подпись SSL).
  • Медиаконвертер: Celery + FastAPI + Redis + Nginx.
  • Две машины: одна для хаба (6/16), вторая для конвертера (4/8).

Скорость работы уже неплохая. Конечно, есть куда расти, но текущая схема решает основные задачи: минимизирует расходы, ускоряет загрузку страниц и упрощает жизнь пользователям.

По деньгам нам это обходится в что-то типа 70 баксов в месяц(два сервера + хранилка). Что вполне себе дорого особенно после копеечных серверов в ЕС. Но закон есть закон. 

62
6
62комментария