
Привет, Хабр! Меня зовут Влад Почернин, я разработчик в команде видеоформатов Дзена. Сегодня расскажу, как мы мигрировали инфраструктуру Дзена на видеоплатформу VK, обслуживающую контент соцплатформ ВКонтакте и Одноклассники, а также видеосервисов VK Видео и VK Клипы.
Переезд стал для нас серьёзным вызовом. Требовалось в сжатые сроки перенести десятки миллионов видео и все связанные процессы: загрузку, транскодинг, хранение, раздачу, админки, пайплайны. К этому добавились специфичные схемы данных старого видеохостинга, интеграции в клиентских приложениях, ML-модели. А также функции, которых не было на видеоплатформе VK, и их мы дорабатывали на лету: антидубли, эмбед-ссылки, музыку, субтитры, трейлеры. За годы существования Дзена накопились десятки петабайт видеоконтента. Особый вызов заключался в том, чтобы внедрить новую систему во все компоненты Дзена и переключить загрузку видео на видеоплатформу без даунтайма и падения продуктовых метрик. Как мы решали эти и другие задачи — расскажу далее.
Процесс переезда: этапы и сложности
Переезд Дзена на видеоплатформу VK прошёл в три ключевых этапа, каждый из которых решал конкретные технические задачи. С организационной точки зрения это был настоящий челлендж: над проектом одновременно работали около десяти команд. Чтобы всё прошло гладко, надо было слаженно взаимодействовать.
Важно было про��умать управление ресурсами — чтобы провести миграцию множества существующих видео в обозримые сроки, понадобился выделенный кластер обработчиков. Требовалось договориться и обосновать, что проект критически важен и должен быть в приоритете. В переговорах нам помогло то, что кластер требовался только на время прокачки уже существующих в Дзене видео.
Этап 0. Экспериментальная прокачка
Первоначально провели полуавтоматическую отправку определённых исходников видео Дзена на новую платформу. Время от времени мы собирали тысячи наиболее просматриваемых за последние несколько дней видео и отправляли их команде видеоплатформы VK в виде набора ссылок на исходники и идентификаторов. А на своей стороне принимали колбэки с простой связкой идентификаторов Дзена и видеоплатформы VK. В старый видеохостинг (далее ВХ) была зашита временная логика раздачи, которая пыталась обратиться за контентом на новую видеоплатформу, но при возникновении проблем возвращала старые ВХ-ссылки. Этот этап позволил провести первые честные A/B-эксперименты: мы включали раздачу новых ссылок на определённую часть пользователей, обсчитывали результаты и могли проверять, что метрики остаются в норме, а явных проблем нет.
Этап 1. Двойная загрузка — напрямую на видеохостинг, асинхронно на платформу VK
Исторически наш старый видеохостинг не только раздавал видео, но и поставлял обработанные данные в различные системы Дзена, например в контент-систему (далее КС). Наладить аналогичное получение данных из видеоплатформы VK тогда было слишком сложно — требовались существенные до��аботки на стороне контент-системы. Но нам нужно было как можно скорее получить MVP, чтобы автоматически передавать на платформу новые видео, которые загружались в Дзен.
Мы выбрали компромиссное решение: реализовали двойную загрузку — напрямую на старый хостинг и асинхронно на видеоплатформу VK. Это оказалось полезно и при адаптации Дзена к новой платформе: при сбое у нас был fallback на старую систему.
Исторически в Дзене использовался протокол TUS — открытый стандарт для передачи больших файлов по HTTP, который способен возобновлять загрузку в случае её прерывания. Спецификация протокола подробно описывает поведение клиента и сервера, уточняя HTTP-заголовки, возможные запросы и коды ответов. Типичные сценарии работы протокола:
Клиент может отправить запрос
OPTIONS, чтобы узнать конфигурацию сервера.Клиент инициализирует загрузку с помощью запроса
POST, указывая размер файла и метаданные (например, имя файла).Клиент может использовать запрос
HEAD, чтобы узнать, сколько данных уже загружено и с какого байта необходимо продолжить загрузку.Клиент отправляет данные с помощью запросов
PATCH, начиная с нужного байта файла.Существует возможность фрагментированной (параллельной) загрузки, при которой клиент разбивает файл на части и загружает каждую независимо (через отдельные
POST- иPATCH-запросы). В конце загрузки отправляется специальный склеивающийPOST-запрос, чтобы объединить фрагменты в один файл.Если загрузка прервалась, клиент может проверить статус загрузки через
HEAD-запрос, получить актуальное смещение и продолжить загрузку с нужного места.
Так выглядела изначальная схема загрузки видео в Дзене:

Когда пользователь начинал загрузку, клиент обращался к бэкенду Дзена для получения URL загрузки. В нашей реализации бэкенд сам решал, разделять ли файл на части, ходил с
POST-запросами в ВХ (в соответствии с TUS) и возвращал клиенту ссылки для загрузки ресурсов.Клиент, используя запросы
OPTIONS,HEADиPATCH, по полученным ссылкам загружал данные в ВХ.После завершения загрузки клиент уведомлял бэкенд Дзена. Тот, кроме прочей бизнес-логики, отправлял в ВХ
POST-запрос для финализации загрузки: склеивания частей (при необходимости) и получения ссылки на итоговый ресурс. Затем ВХ начинал обработку видео и оповещал о ней наш бэкенд через колбэки.Когда пользователь нажимал «Опубликовать» или подходило время отложенной публикации, и когда видео оказывалось обработанным на ВХ, происходила его фактическая публикация. Наш бэкенд информировал об этом контентную систему, которая скачивала видео и метаданные c ВХ и выполняла важные манипуляции с обработанным файлом: модерацию, обогащение документов и так далее.
На первом этапе интеграции мы добавили в схему асинхронную отправку метаданных о видео (в том числе ссылку для скачивания исходника) на новую видеоплатформу после завершения загрузки на ВХ. Инфраструктура платформы получала ивент, скачивала исходник и начинала его обработку у себя, также отправляя нам колбэки.

Одной из наших ключевых задач на этом этапе было синхронизировать статусы обработки между ВХ и платформой VK. Требовалось, чтобы новые видео могли публиковаться только после их обработки на обеих платформах. Если ролик публиковался слишком рано (например, после обработки только на ВХ), возникал риск, что в контентную систему не успеет попасть необходимая информация от видеоплатформы VK.
Во время разработки и тестирования это не вызывало вопросов — видео могли попадать в контентную систему, даже если были обработаны только на старом видеохостинге. Информация от платформы в таких случаях попадала бы в КС позже — во время миграции существующих видео Дзена. Но для нас было важно чётко определить точку перехода, с которой все новые видео должны были попадать в контентную систему только после полной обработки на обеих платформах. Это позволяло ограничить задачу прокачки существующих видео только контентом, загруженным до этого момента.
Основная сложность синхронизации статусов обработки между видеоплатформами заключалась в большом количестве проверок и их разнообразии. Статусы обрабатывались как через логические выражения в коде, так и с помощью запросов в базу данных. Логика могла быть сложной и многоуровневой, и это требовало особой аккуратности при объединении условий. Особенно с учётом того, что на этом этапе мы могли временно отключать отправку новых видео на платформу VK, а это не должно было сказываться на пользовательском опыте. Корректность этих проверок напрямую влияла на сценарии работы платформы: публикацию (в том числе отложенную), отображение видео в студии и ряд других функций.
Отдельные сложности возникали при работе с фильтрами в MongoDB. Иногда наивно составленный запрос отказывался работать из-за особенностей библиотеки, связывающей Java-код с MongoDB. Ещё мы несколько раз сталкивались с риском серьёзной деградации производительности после добавления новых фильтров в запросы. Они переставали попадать в существующие индексы, и время выполнения таких запросов резко возрастало. Мы тщательно отлавливали подобные граничные случаи, добавляя необходимые индексы.
Таким образом, реализация логики сопоставления старых и новых статусов обработки видео требовала максимального внимания к деталям — только так можно было избежать критических ошибок и инцидентов. Здесь нам часто приходилось искать компромиссные решения и обходные пути.
Отдельным мини-вызовом стала реализация распределённой блокировки по конкретному видео, на которое одновременно могли приходить колбэки как от ВХ, так и от видеоплатформы VK. Это могло вызвать состояние гонки при обновлении информации в базах данных. Отличным решением стал Curator Framework: он предоставляет из коробки удобные методы по работе с блокировками в ZooKeeper.
Наконец, на этом этапе мы подняли отдельный сервис, инкапсулирующий в себе логику раздачи ссылок на видеоконтент. До этого сервисы Дзена, которым было нужно получить видео, ходили за ними напрямую в ВХ. Наш сервис получал запрос в привычном для клиентов виде и шёл по gRPC на видеоплатформу VK, чтобы получать необходимую информацию. С этим подходом у нас получилось настроить подробный дашборд состояния раздачи, а также интегрировать важный элемент надёжности — gRPC-кеш. Это выделенный gRPC-метод, в который сервис шёл в первую очередь. Этот метод по сути был кешем на стороне платформы VK. Он обеспечивал доступность видео при падении основного видеосервиса и существенно сокращал среднее время получения запрашиваемых данных.
Бонусом мы научились воспроизводить видео в формате MP4. Это позволило показывать их пользователям намного быстрее: видеоплатформа, в отличие от ВХ, могла раздавать оригинальные видео (исходники), пока идёт транскодирование в другие качества и форматы (HLS, DASH и так далее).
Включение новой функциональности
Расскажу, как мы раскатывали новую функциональность. Загрузка видео выкатывалась отдельно от раздачи, а для гранулярного включения фич использовались AB-эксперименты и разные рубильники, которые можно настраивать как на конкретных пользователей, так и на их процент. Раздачу видео включали раздельно по различным платформам и версиям приложений Дзена.
Первые A/B-эксперименты мы проводили в веб-версии Дзена, затем начали добавлять в них версии Android- и iOS-приложений. По мере переключения раздачи периодически обнаруживали несоответствия платформ, проводили доработки и вновь пытались переключать. Мы плотно покрыли тестированием веб и актуальные версии мобильных приложений. Но покрыть весь хвост версий было невозможно. Поэтому, чтобы своевременно реагировать на проблемы, мы по максимуму использовали приборные метрики, построенные на отправляемых клиентами событиях.
Здесь нас встретил неожиданный инцидент: на старых версиях приложений переключение раздачи на видеоплатформу VK ломало в них проигрывание видео. Для локализации проблемы нам пришлось подключать разработчиков к реверс-инжинирингу. Причину нашли в формате передаваемых ссылок. Исторически в них было необходимо записывать определённые legacy-параметры. Они продолжали возвращаться в ВХ-ссылках, даже когда такую необходимость удалили в актуальных версиях приложений. А в видеоплатформе VK их, конечно, не было. В итоге проблему удалось решить патчингом для этих версий ссылок на стороне нашего бэкенда.
Этап 1.5. Миграция существующих видео Дзена на видеоплатформу VK
Наработки с предыдущего этапа позволили нам параллельно запустить прокачку уже существующих видео Дзена на платформу VK. Этот этап развивался и поддерживался независимо от остальных, поскольку был сильно растянут во времени — было много работы для кластера видеоплатформы.
В отличие от вновь загружаемых видео, существующие ролики уже были успешно обработаны на старом ВХ и прошли КС. Возникали две отдельные задачи. С одной стороны, было нужно подготовить и отправить на видеоплатформу VK большой объём видеороликов в исходном качестве для их обработки. С другой, процесс реагирования на результат обработки требовал особого подхода. Эти видео уже прошли модерацию, активно показывались и попадали в рекомендации пользователям. А значит, было не нужно повторно запускать их обработку контентной системой на нашей стороне. Это было бы очень дорого — по большей части за счёт работы модерации. Поэтому к проблеме подошли разумно: сделали запись только необходимых данных, не вызывая повторное прохождение КС.
В результате алгоритм миграции выглядел так:
Формирование списка актуальных видео
В первую очередь мы определили список живых записей — тех, которые были успешно загружены и обработаны на ВХ. Количество таких видео оказалось впечатляющим: более 45 миллионовСбор и подготовка метаданных
Для каждого видео из полученного списка мы извлекли метаданные и ссылки на исходники (старый видеохостинг хранил оригиналы). На их основе формировались таблицы в YTsaurusОрганизация передачи данных через Kafka
Под процесс передачи данных выделили отдельный Kafka-топик — рядом с топиком, который уже использовался для асинхронной загрузки новых видео на платформу VK. Параллельно реализовали специальный обработчик колбэков от платформы для уже существующего контента (то есть для миграции)Запуск миграции
Для отправки подготовленных данных на платформу VK разработали и запустили отдельный процесс. Скорость работы мы могли регулировать динамически без его остановки. Так, опираясь на загруженность обработчиков видеоплатформы, подбирали оптимальную скорость миграцииОбработка колбэков и начало раздачи видео
После загрузки видео на видеоплатформу и завершения его обработки мы принимали от видеоплатформы колбэк-запросы, проставляли необходимые данные во внутренних системах и начинали раздачу контента уже с новой системы. Такой подход обеспечивал быструю и бесшовную миграцию существующих видео незаметно для пользователей
Были и свои сложности. Начав подбирать максимально возможную скорость отправки видео, при которой видеоплатформа VK успевала бы их обрабатывать, мы обнаружили, что при изначально выделенных ресурсах процесс занял бы несколько лет. Конечно, столько мы ждать не могли — и после дополнительных согласований получили выделенный кластер. Это сократило предполагаемые сроки прокачки до нескольких месяцев.
Кластер насчитывал 1 400 серверов, в каждом из которых было:
8 ядер CPU;
64 Гб ОЗУ;
1 000 Мб сети IN;
1 000 Мб сети OUT.
Всего было выделено 11 200 ядер, а утилизация некоторых хостов в пиковые моменты превышала 900%. В среднем они использовали 300% в зависимости от загруженности дата-центра: наше облако способно выделять отдельным репликам CPU больше запрошенного, если есть свободное железо.
Скорость также подбиралась динамически — в зависимости от сложности контента. Например, проще всего переваривались короткие ролики, сложнее — обычные видео. По мере движения по таблице всё чаще попадались записи с высоким разрешением, обработка которых требовала больше времени.
В среднем мы шли на скорости в 700 тысяч видео в сутки, разгоняясь в пике до 3 миллионов. По мере прохождения миграции существующих видео мы наблюдали на графиках всё больший процент раздачи из видеоплатформы VK по сравнению со старым видеохостингом.
Ещё одна неожиданность для нас — для некоторой части видео (нескольких десятков тысяч) у ВХ пропали исходники. Допустить потерю стольких публикаций мы не могли. Поэтому отдельно реализовали механизм, который позволил бы видеоплатформе скачивать такие записи напрямую из раздаваемого ВХ контента.
Механизм отправки метаданных после основной миграции также применили для передачи на видеоплатформу трейлеров и субтитров. Это помогло избежать большого объёма вычислений на стороне платформы.
Этап 2. Двойная загрузка — напрямую на видеоплатформу VK, асинхронно на ВХ
На втором этапе мы внедрили прямую интеграцию, реализовав загрузку файлов с клиентов в новую платформу. Однако полностью отказаться от старого ВХ на тот момент было невозможно — контентная система для корректной обработки всё ещё требовала, чтобы видео загружалось на обе платформы. Поэтому мы инвертировали и немного изменили архитектуру процесса:

Взаимодействие нашего бэкенда с видеоплатформой VK происходило по gRPC вместо аналогичного взаимодействия с ВХ через POST-запросы. Здесь инициализация и завершение загрузки фактически происходили на стороне видеоплатформы
В пункте 3 на схеме видеоплатформа VK и ВХ поменялись местами
Это решение позволило нам перенести основной поток загрузок видео напрямую в новую платформу, сохраняя совместимость с существующей инфраструктурой Дзена. В дальнейшем, когда необходимость в ВХ отпала бы, планировалось полностью перейти на загрузку только на видеоплатформу VK.
Однако на этом этапе нас также ожидали сюрпризы:
Изначально, чтобы обеспечить плавный переход и не ломать привычный API для клиентов Дзена, мы запланировали разработку TUS-сервера на стороне платформы VK.
В стандартном расширении протокола TUS — Concatenation, которое использует Дзен, клиент разбивает файл на несколько независимых partial-загрузок. В конце он отправляет серверу запрос на финальный upload, где перечисляет эти загрузки в нужном порядке.
При реализации подхода поверх объектного хранилища видеоплатформы VK это превратилось в отдельную операцию склейки. Сначала все фрагменты записывались как самостоятельные объекты, а затем на стороне сервера из них собирался итоговый файл.
Для больших видео такой второй проход по данным давал ощутимую дополнительную нагрузку по I/O и времени, фактически сравнимую с повторной загрузкой файла.
Дополнительно на новой платформе поверх загрузки работали фоновые процессы обработки контента. Они видели уже появившиеся фрагменты и могли вмешиваться в долгую операцию склейки, если та не успевала завершиться до начала очередного фонового процесса.
Как итог — классическая реализация TUS с конкатенацией поверх нового хранилища оказалась для нас слишком тяжёлой и нестабильной.
Перевести веб-клиент Дзена на стандартную систему загрузки видеоплатформы VK было технически возможно. Но оставалась критическая проблема с поддержкой устаревших мобильных клиентов Android и iOS, которые изначально были заточены именно под TUS. Внедрение нового протокола загрузки без обратной совместимости означало бы, что значительная часть пользователей Дзена не сможет загружать видео.
Мы решили эту задачу: видеоплатформа VK смогла адаптировать наш контракт загрузки под свой стандартный механизм. Сейчас наши клиенты отправляют те же HTTP-запросы, а видеоплатформа принимает их и преобразует в формат, привычный для своего загрузчика. Это кастомное решение не было чистым TUS по спецификации, но такой компромисс помог выполнить наши задачи и уложиться в сроки проекта.
Этап 3. Загрузка только на видеоплатформу VK
На завершающем этапе мы полностью отказались от старого видеохостинга. Контентная система больше не требовала наличия видео на обеих платформах, и мы смогли отключить асинхронную загрузку на ВХ.
Схема стала идентична первой, за исключением нюанса с общением бэкенда и видеоплатформы через gRPC вместо HTTP.

Но здесь нас вновь поджидал неожиданный челлендж. Оказалось, что ML-эмбеддинги, вычисляемые по видео, обработанному в видеоплатформе VK, существенно отличались от тех, что получались при загрузке его через ВХ. Это могло повлиять на качество рекомендаций и другие ML-сервисы. Из-за сжатых сроков мы не могли полноценно переработать ML-процессы под обработку контента от новой платформы.
Нашли компромисс: договорились получать от видеоплатформы VK исходные загруженные файлы (оригиналы), которые затем использовались для расчёта эмбеддингов. Так мы минимизировали расхождения между результатами ML-обработки и обеспечили приемлемое качество работы сервисов.
После этого окончательно отключили асинхронную загрузку на старый ВХ. Это высвободило значительные ресурсы, которые раньше шли на двойную обработку видео. Мы продолжаем использовать эту архитектуру — она полностью удовлетворяет нашим требованиям и позволяет эффективно масштабировать систему.
Ретроспектива
Переезд Дзена на видеоплатформу VK оказался сложным и масштабным проектом, потребовал тщательной организации и командной работы. Почти на каждом этапе мы сталкивались с неожиданными трудностями — от несовместимостей на старых версиях мобильных клиентов до поисков потерянных исходников в процессе миграции. Приходилось быть гибкими в решениях и осторожными во время опасных переключений.
Ещё было важно приоритизировать задачи и сфокусироваться на MVP. Это позволило относительно быстро получить рабочий вариант интеграции, а затем дорабатывать систему по мере движения к целевому результату (отрыву старого ВХ). Двойная загрузка на обе видеоплатформы на стадии MVP не раз спасала нас от проблем в процессе интеграции.
Чтобы запускать разрабатываемую логику точечно и безопасно, мы использовали умные рубильники. Благодаря этому могли включать код для себя и тестировщиков, постепенно раскатывать изменения на ограниченную аудиторию, тестировать функциональность без риска для основной массы пользователей и быстро реагировать на любые проблемы.
Один из главных выводов проекта: даже к самым сложным и, казалось бы, неразрешимым проблемам всегда можно подойти гибко. Найти компромисс, срезать углы, договориться с коллегами о допустимом решении. Примером здесь может служить адаптация протокола TUS под систему загрузки видеоплатформы VK. Благодаря этому компромиссу и другим подобным решениям мы реализовали проект, не теряя в качестве и не откладывая запуск на неопределённые сроки.
Результат переезда
Переход на новую видеоплатформу дал Дзену и его пользователям множество улучшений и новых возможностей. Одно из самых заметных изменений — поддержка видео в высоких разрешениях: 2K и 4K.
Также раньше мы наблюдали проблемы при загрузке видео на ВХ: пользователи часто обращались в техническую поддержку. При переходе на платформу VK подобных обращений стало существенно меньше.
Из технических улучшений — время ответа видеохостинга снизилось с 60 до 40 миллисекунд в 99-м перцентиле. Общий процент ошибок уменьшился, а сама система теперь стабильно выдерживает нагрузку порядка 30 тысяч запросов в секунду на раздачу видео.
Мы добавили механизм gRPC-кеша для повышения надёжности и скорости ответа видеосервиса. Он страхует нас от случайного сбоя основного сервиса раздачи видео на стороне видеоплатформы, в то же время выступая в роли кеша. Внедрение этого механизма помогло повысить отказоустойчивость и производительность нашего сервиса.
Наконец, видеоплатформу VK используют различные бизнес-юниты группы компаний. Одни и те же видео, загружаемые в различные продукты, можно хранить в единственном экземпляре, обрабатывать единожды и раздавать их там, где это необходимо. Утилизация железа при таком подходе также более выгодна, чем при использовании собственных решений и инсталляций для каждого из продуктов.
Переезд Дзена показывает, как сложные инфраструктурные изменения могут принести заметные бенефиты и пользователям, и бизнесу. Если вам близки такие задачи или есть опыт внедрения масштабных изменений — поделитесь своим мнением и кейсами в комментариях!
