![](https://habrastorage.org/getpro/habr/upload_files/d61/91e/8d6/d6191e8d6ce52133d61d9baefa5bbd49.png)
Netflix Cosmos — это вычислительная платформа, которая сочетает в себе самые лучшие аспекты микросервисов, а также поддержку асинхронных рабочих процессов и бессерверных функций. Наш конек — это разработка приложений, реализующих ресурсоемкие алгоритмы, которые координируются с помощью сложной иерархии рабочих процессов и охватывают разные временные отрезки — от нескольких минут до нескольких лет. Платформа обеспечивает функционирование не только сервисов с высокой пропускной способностью, в которых параллельно задействованы сотни тысяч процессоров, но и чувствительных к задержке рабочих нагрузок, при которых важно как можно быстрее показать результаты пользователям..
![Сервис Netflix Cosmos Сервис Netflix Cosmos](https://habrastorage.org/getpro/habr/upload_files/5bc/14d/71c/5bc14d71cf00ca51b6d036ff44b18299.png)
В этой статье мы расскажем, почему мы решили создать платформу Netflix Cosmos, как она работает, а также поделимся полезным опытом, который мы накопили в ходе проекта.
Предыстория
В Netflix есть два подразделения, которые совместно отвечают за обработку входящих медиафайлов от наших партнеров и студий и обеспечивают воспроизведение контента на всех пользовательских устройствах, — это Media Cloud Engineering и Encoding Technologies. Первое поколение системы мы запустили для нашего стримингового сервиса в 2007 году. В решении второго поколения было проведено масштабирование для поддержки большого числа пользователей. Однако такой системой оказалось очень сложно управлять. Система третьего поколения — Reloaded — работает уже около семи лет. За это время она успела доказать свою стабильность и высокую масштабируемость.
При создании версии Reloaded у нас было очень мало разработчиков и мы использовали небольшой вычислительный кластер. Перед нами стояла узкая задача: создание конвейера для обработки видео и аудио. Время шло, число наших разработчиков увеличилось более чем в три раза, мы создали и глубоко проработали огромное количество новых бизнес-сценариев, при этом объем данных в системе увеличился более чем в десять раз. Наличие монолитной архитектуры существенно замедляло выпуск нового функционала. Каждый из нас уже физически не мог обладать всем объемом специальных знаний, необходимых для создания и внедрения новых возможностей. Решение рутинных проблем на продакшне стало тяжким бременем для всех разработчиков, поскольку инфраструктурный код был перемешан с прикладным кодом. Централизованная модель данных, которая хорошо подходила для небольшой команды, теперь стала помехой.
В итоге мы создали Netflix Cosmos — основанную на рабочих процессах платформу для микросервисов, ориентированных на медиа. Наша первоочередная задача заключалась в том, чтобы сохранить текущий функционал, при этом обеспечив:
наблюдаемость — свойство, которое мы поддерживаем за счет встроенных механизмов журналирования, трассировки, мониторинга, оповещения, а также классификации ошибок;
модульность — специализированный фреймворк, позволяющий структурировать сервис и обеспечить его модульность как с точки зрения времени компиляции, так и времени исполнения кода;
производительность разработки — локальные инструменты для разработчиков, включая специализированные исполнители тестового кода, генераторы кода, а также интерфейс командной строки;
развертывание — полностью управляемая система конвейерного развертывания сервисов, непрерывного выполнения интеграционных заданий, а также комплексного тестирования. После мержа пулреквесты сразу попадают в продакшн без необходимости каких-либо ручных действий.
Наряду с этим мы также повысили надежность, масштабируемость, безопасность и другие качества системы.
Введение
Netflix Cosmos не является микросервисом, однако обладает неким сходством с ним. Обычно микросервис — это API‑интерфейс, который реализует бизнес-логику без сохранения состояния (stateless) и автоматически масштабируется в зависимости от объема поступающих запросов. API‑интерфейс заключает строгие контракты с взаимодействующими с ним системами, при этом поступающие от разных систем данные приложений и бинарные зависимости хранятся отдельно друг от друга.
![Обычный микросервис Обычный микросервис](https://habrastorage.org/getpro/habr/upload_files/30e/169/862/30e169862994a135634af241af071d08.png)
В Netflix Cosmos сохраняются характерные для микросервиса строгие контракты и сегрегация данных, но также добавляются многоуровневость рабочих процессов и ресурсоемкие асинхронные функции для бессерверных вычислений. На приведенной ниже диаграмме стандартного сервиса Netflix Cosmos клиенты отправляют запросы к API‑сервису на уровень видеокодера. Управление этапами рабочего процесса ведется при помощи набора правил. При этом набор бессерверных функций управляет алгоритмами, специфичными для предметной области. Функции упаковываются в виде образов Docker вместе с бинарными зависимостями (например, как пакеты Debian) для поддержки конкретных типов медиаданных. Функции масштабируются в зависимости от размера очереди и могут выполняться на десятках тысяч разных контейнеров. Выполнение запросов может занять несколько часов или даже дней.
![Обычный сервис Netflix Cosmos Обычный сервис Netflix Cosmos](https://habrastorage.org/getpro/habr/upload_files/54b/ed3/24b/54bed324bd015699287ce4745eec0ec6.png)
Разграничение функциональности
Netflix Cosmos имеет две оси функционального разграничения. С одной стороны, существует разграничение логики между API‑интерфейсом, рабочим процессом и бессерверными функциями. С другой стороны, существует разграничение логики между приложением и платформой. API‑интерфейс платформы выдает разработчикам приложений абстрактные представления для конкретных типов медиаданных, при этом технические подробности реализации распределенных вычислений скрываются. Например, сервис видеокодера состоит из компонентов, не зависящих от масштаба: это просто API‑интерфейс, рабочий процесс и функции. Эти компоненты не обладают информацией о масштабах, в которых они работают. Специфичные для предметной области и не зависящие от масштаба компоненты построены поверх трех подсистем Netflix Cosmos, которые уже учитывают масштаб и отвечают за конкретные особенности распределенных вычислений:
Optimus — API‑уровень, который переводит внешние запросы на язык внутренних бизнес‑моделей;
Plato — уровень рабочих процессов, который позволяет моделировать бизнес‑правила;
Stratum — уровень бессерверных вычислений, который предназначен для выполнения ресурсоемких и stateless‑функций.
Все подсистемы взаимодействуют друг с другом асинхронно через Timestone — широкомасштабную систему приоритетной обработки очередей с низкой задержкой. Каждая подсистема отвечает за свой сегмент задач сервиса и может быть развернута независимо от других при помощи целевого управляемого процесса непрерывного развертывания. Подобное функциональное разграничение облегчает создание, тестирование и эксплуатацию сервисов Netflix Cosmos.
![Разделение между платформой и приложением. Разделение между платформой и приложением.](https://habrastorage.org/getpro/habr/upload_files/593/463/641/593463641647e2638cfeff2c1a175bf5.png)
Сервисный запрос в Netflix Cosmos
![График трассировки сервисного запроса в Netflix Cosmos. График трассировки сервисного запроса в Netflix Cosmos.](https://habrastorage.org/getpro/habr/upload_files/4d7/cf1/212/4d7cf12128c982a7608ef5a5a9b0374a.png)
На рисунке выше показан скриншот из сервиса Nirvana — нашего портала, отвечающего за наблюдаемость. Перед вами стандартный запрос в Netflix Cosmos (в данном случае — к сервису видеокодера):
Видеокодер получил один API‑вызов с указанием источника видео и рецепта кодирования.
Видео разбивается на 31 фрагмент, что позволяет параллельно запустить 31 функцию кодирования.
Функция сборки вызывается один раз.
Функция индексирования вызывается один раз.
Рабочий процесс завершается через восемь минут.
Уровни сервисов
Netflix Cosmos поддерживает декомпозицию сервисов с последующим распределением по уровням. Полученная модульная архитектура позволяет каждой команде разработчиков сосредоточиться на конкретной области специализации, прицельно контролируя собственные API‑интерфейсы и релизные циклы.
Например, видеосервис, упомянутый выше, — это один из множества сервисов для создания видеопотоков, воспроизводимых на устройствах. Такого рода сервисы, обеспечивающие среди прочего проверку видеоматериалов, создание аудио и текста, а также упаковку контента, управляются с использованием сервисов более высокого уровня. Крупнейший и наиболее сложный из таких сервисов — это Tapas. Он отвечает за получение исходного видеоконтента от студий и преобразование их в формат, воспроизводимый на Netflix. Еще один высокоуровневый сервис — это Sagan. Он предназначен для поддержки студийных процессов, включая выпуск маркетинговых клипов и создание ежедневных студийных редакционных копий.
![Уровни сервисов Netflix Cosmos. Уровни сервисов Netflix Cosmos.](https://habrastorage.org/getpro/habr/upload_files/840/82a/119/84082a119b6db198c3b29c9f0baff243.png)
Когда из продакшн-студии поступает новый материал, запускается рабочий процесс Tapas, который управляет запросами на такие виды операций, как:
проведение проверок;
кодирование видео в нескольких экранных разрешениях, с разными кодеками и разным качеством;
кодирование аудио несколькими кодеками в разном качестве;
генерация субтитров на нескольких языках;
упаковка полученных результатов для нескольких форматов плееров.
Таким образом, в результате одного запроса к сервису Tapas могут сформироваться сотни запросов к другим сервисам Netflix Cosmos и тысячи вызовов функций сервиса Stratum.
Ниже приведена трассировка, показывающая, как запрос к сервису верхнего уровня может распределяться по сервисам более низкого уровня и запускать широкий спектр действий. В этом случае на обработку запроса ушло 24 минуты, причем было выполнено несколько сотен разных действий с использованием 8 сервисов Netflix Cosmos и 9 функций Stratum.
![Трафик трассировки запроса к сервису на нескольких уровнях. Трафик трассировки запроса к сервису на нескольких уровнях.](https://habrastorage.org/getpro/habr/upload_files/54a/5f9/662/54a5f96622b7af8b27ce49bea777f2d0.png)
Всем правят рабочие процессы!
А может, лучше «правила рабочих процессов»? Plato — это своеобразный клей, который связывает воедино все компоненты Netflix Cosmos, предоставляя разработчикам сервисов мощный фреймворк для определения специализированной логики и управления функциями и сервисами без сохранения состояния. Уровень API Optimus имеет встроенные средства для вызова рабочих процессов и проверки их состояния. Уровень бессерверных вычислений Stratum формирует строго типизированные клиенты RPC, позволяющие легко и удобно вызывать serverless-функции.
Plato — это система правил с прямой логической цепочкой, которая позволяет учесть асинхронность и ресурсоемкость наших алгоритмов. В отличие от процедурного движка рабочих процессов, например Netflix Conductor, система Plato позволяет с легкостью создавать рабочие процессы «непрерывного цикла». Например, в случае доработки алгоритмов кодирования правила рабочих процессов позволяют автоматически запустить обновление существующих видео без необходимости запуска новых рабочих процессов и управления ими. Кроме того, любой рабочий процесс может вызвать другой процесс, что позволяет использовать несколько сервисных уровней, о чем мы говорили выше.
Plato является многопользовательской системой на базе Apache Karaf, что значительно снижает операционную нагрузку на управление рабочим процессом. Пользователи создают и тестируют правила в собственном репозитории исходного кода, а затем разворачивают рабочий процесс путем загрузки скомпилированного кода на сервер Plato.
Разработчики определяют рабочие процессы, задавая наборы правил на учитывающем особенности предметной области языке Emirax, созданном на базе Groovy. Каждое правило состоит из четырех разделов:
match — указывает условия, при выполнении которых должно сработать правило;
action — указывает код, который будет выполняться при срабатывании правила (именно здесь вы вызываете функции Stratum для обработки запроса);
reaction — указывает код, который будет выполнен после успешного завершения кода action;
error — указывает код, который будет выполняться при обнаружении ошибки.
В каждом из этих разделов обычно сначала записывается изменение состояния рабочего процесса и только затем выполняются шаги для его продвижения вперед, например выполнение функции Stratum или возврат результатов выполнения (подробности — в презентации на feathercast.apache.org).
Приложения, чувствительные к задержке
Такие сервисы Netflix Cosmos, как Sagan, чувствительны к задержке, поскольку взаимодействуют с конечным пользователем. Например, автор, который собирается опубликовать пост в социальных сетях, вряд ли готов ждать, пока вырежется клип из последнего сезона «Бумажного дома». Для Stratum латентность зависит от времени, необходимого для выполнения работы, плюс времени, необходимого для получения вычислительных ресурсов. В условиях пикового спроса на выполнение работ (а это бывает часто) время на получение ресурсов становится значимым фактором. Возьмем для иллюстрации такой пример. Вы идете в магазин, один из пунктов в вашем списке продуктов — туалетная бумага. Как правило, нет никаких проблем с тем, чтобы положить рулон в корзину и выстоять очередь в кассу: весь процесс займет каких-нибудь 30 минут.
![Нехватка ресурсов. Нехватка ресурсов.](https://habrastorage.org/getpro/habr/upload_files/dd6/9a2/c4f/dd69a2c4f1070b99df62b3f1a8c75c57.png)
Затем в один прекрасный день приходит эпидемия зловредного вируса — и каждому приходит в голову, что стоит закупить побольше туалетной бумаги. Теперь ваша задержка с туалетной бумагой составит от 30 минут до двух недель, поскольку общий спрос превышает имеющиеся производственные мощности. Приложения Netflix Cosmos (в частности, функции Stratum) сталкиваются с той же проблемой в условиях пикового и непредсказуемого спроса. Stratum решает проблему задержки при выполнении функций несколькими способами:
Пулы ресурсов — конечные пользователи могут зарезервировать вычислительные ресурсы Stratum для своего сценария использования. При этом пулы ресурсов имеют иерархическую структуру, что позволяет пользователям создавать группы и пользоваться ресурсами совместно.
Разогрев ресурсов — конечные пользователи могут заранее запросить вычислительные ресурсы (например, контейнеры) и снизить задержки, связанные с их запуском в Stratum.
Микропакеты сервисных ресурсов — этот трюк используется на таких платформах, как Apache Spark, чтобы снизить задержку при запуске. Идея в том, чтобы разделить стоимость запуска на несколько вызовов функций. Если вы вызываете функцию 10 000 раз, она может выполниться по одному разу на 10 000 контейнеров или по 10 раз на 1000 контейнеров.
Приоритет — с позиций балансировки стоимости с целью снижения задержки, сервисы Netflix Cosmos обычно оказываются где-то в середине шкалы: ресурсов хватает для обработки обычных пиковых нагрузок, но их недостаточно для обработки крупномасштабных пиков, требующих минимальных уровней задержки. Благодаря расстановке приоритетов приложения могут гарантировать, что самая важная работа будет выполнена с низкой задержкой, даже если ресурсов недостаточно. Владельцы сервисов Netflix Cosmos могут либо разрешить конечным пользователям самостоятельно устанавливать приоритет, либо установить его централизованно на уровне API или рабочего процесса.
Приложения, чувствительные к пропускной способности
Такие сервисы, как Tapas, чувствительны к пропускной способности, поскольку они потребляют большие объемы вычислительных ресурсов (до несколько миллионов процессорных часов в день). Их больше волнует возможность выполнить большой объем задач за несколько часов или дней, а не время выполнения отдельной задачи. Другими словами, цели уровня обслуживания (SLO) в данном случае измеряются числом задач в день и стоимостью в расчете на одну задачу, а не числом выполняемых задач в секунду.
Для рабочих нагрузок, чувствительных к пропускной способности, наиболее важные SLO — это те, которые предоставляются бессерверным уровнем Stratum. Stratum создан на базе контейнерной платформы Titus и позволяет чувствительным к пропускной способности рабочим нагрузкам «оппортунистически» использовать вычислительные ресурсы благодаря возможностям гибкого планирования. Например, стоимость вызова serverless-функции может оказаться ниже, если допустима задержка выполнения вплоть до часа.
Модель фикуса-душителя
Мы прекрасно отдавали себе отчет, что перенос существующей системы, тем более такой большой и сложной, как Reloaded, будет большим прыжком через опасную пропасть, усеянную осколками неудачных проектов по реинжинирингу. Однако у нас не оставалось никаких сомнений в том, что прыгнуть мы должны. Чтобы снизить свой риск, мы решили использовать так называемую модель фикуса-душителя — она позволяет новой системе расти вокруг старой и в конечном итоге полностью заменить ее.
Продолжаем учиться
Мы начали работать над Netflix Cosmos в 2018 году и запустили систему в продакшн в начале 2019 года. На сегодняшний день у нас работает порядка 40 сервисов Netflix Cosmos и мы ожидаем, что этот список будет расширяться. Мы еще в середине пути, но у нас уже есть наработки, которыми мы готовы поделиться.
Культура Netflix сыграла ключевую роль
Культура разработки в Netflix строится на приоритете личного мнения сотрудников, а не на директивном контроле «сверху вниз». Наши разработчики обладают всей полнотой свободы и ответственности, что позволяет им самостоятельно брать на себя риски и принимать решения. У нас нет громкой должности архитектора программного обеспечения — каждый из нас на своем уровне играет эту роль. Именно поэтому фреймворк Netflix Cosmos возник вследствие разнородных попыток локальной оптимизации. Optimus, Plato и Stratum были задуманы независимо друг от друга и в конечном итоге слились в единое видение всей платформы в целом. Разработчики приложений делали акцент на удобстве API‑интерфейсов и производительности разработчиков. Именно благодаря мощному партнерству между разработчиками инфраструктуры и разработчиками медиа-алгоритмов мы смогли воплотить наше видение в реальность. В условиях директивной разработки это едва ли было бы возможно.
Микросервис + рабочий процесс + бессерверные технологии
Мы обнаружили, что программная модель «микросервисы запускают рабочие процессы, которые управляют serverless-функциями» — это действительно очень мощная парадигма. Она хорошо работает в большинстве наших сценариев. Однако некоторые приложения слишком просты, и потенциальные преимущества не стоят усилий по наращиванию сложности.
Платформенный подход
Переход от крупномасштабного распределенного приложения к архитектуре «платформа плюс приложения» стал для нас серьезным сдвигом парадигмы. Каждому из нас в той или иной мере пришлось поменять стиль мышления. Разработчикам приложений пришлось в какой-то степени отказаться от гибкости в обмен на согласованность, надежность и т. д. Разработчики платформы должны были проявить эмпатию и уделить приоритетное внимание обслуживанию клиентов, производительности работы пользователей, а также уровням обслуживания. В какие-то моменты разработчики приложений чувствовали, что разработчики платформы не уделяли должного внимания их потребностям. В других ситуациях разработчики платформы, наоборот, чувствовали себя перегруженными требованиями со стороны пользователей. Мы смогли преодолеть все эти непростые моменты благодаря открытости и честности друг с другом. Например, недавний ретроспективный анализ показал, что в целом по всем нашим процессам разработки наибольший акцент делается на системных качествах, таких как опыт разработки, надежность, наблюдаемость и безопасность.
Платформа живет и побеждает
Начиная работу над Netflix Cosmos, мы ставили цель повысить качество и скорость разработки, дать инженерам возможность уделять больше времени бизнес-задачам и меньше времени — поддержке инфраструктуры. Временами цель казалась зыбкой и недоступной, но теперь мы уже начинаем видеть те результаты, на которые надеялись. Разработчики больше всего ценят Netflix Cosmos за такие системные качества, как управляемое развертывание сервисов, модульность, наблюдаемость, а также поддержка для разработчиков. Мы стараемся усилить эти качества, одновременно работая над более слабыми областями, такими как локальная разработка, устойчивость и тестируемость.
Планы на будущее
2021 год станет для Netflix Cosmos годом больших свершений: мы перенесем большую часть нашей работы из Reloaded в Cosmos, выделим на проект дополнительных разработчиков и нарастим рабочие нагрузки на инфраструктуру. Мы планируем развивать нашу модель программирования и включить в нее новые сценарии использования. Наша цель заключается в том, чтобы сделать Netflix Cosmos более простым в использовании, более устойчивым, быстрым и эффективным. Подписывайтесь на наш блог — мы расскажем вам еще больше о том, как работает Netflix Cosmos и как мы используем этот фреймворк.