обратно в блог
  • backend
  • product
  • analytics

Будьте в курсе всех возможностей

Нужна ли вам платформа на самом деле?

Привет, я Саша. В Яндекс Еде я руковожу разработкой, и сегодня хочу поговорить на тему, которая, кажется, уже успела набить оскомину — о платформах. Все понимают под этим словом что-то своё: одни представляют Kubernetes, другие — фреймворк, третьи — набор готовых сервисов с общей бизнес-логикой.

В этой статье я постараюсь не грузить вас скучной теорией. Вместо этого расскажу как мы пришли к созданию своей платформы Goliath и что в неё заложили. И, что не менее важно, как мы её внедряли: как убеждали разработчиков и продакт-менеджеров и почему к внутренней разработке стоит подходить как к полноценному продукту. А ещё попробуем разобраться с тем, нужна ли платформа именно вам. В общем, будет интересно.

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

Раскладываем платформу по полочкам

Сразу оговорюсь, что это не какая-то общепринятая классификация, а скорее наша внутренняя ментальная модель, которая помогает навести порядок в архитектуре.

01 (9).png

Для себя мы выделяем три условных слоя, из которых может состоять платформа:

1. Инфраструктурный слой. Это самый низкий уровень, близкий к железу. Это может быть Kubernetes, облачные инфраструктурные сервисы, управляемые базы данных — всё то, что обеспечивает запуск и работу нашего кода. В том или ином виде этот слой есть у всех, и тут редко возникают споры.

3. Продуктовый слой. Это противоположный полюс — готовые платформы с конкретной, переиспользуемой бизнес-логикой. Например, у нас есть «хранилище товаров» — сложная система из множества микросервисов, которая позволяет разным командам эффективно работать с каталогом. Такие продуктовые платформы обычно появляются органично, когда какая-то часть бизнес-логики становится настолько востребованной, что её выносят в отдельный набор сервисов.

И между этими двумя слоями находится самый интересный и спорный — второй.

2. Библиотечный слой. Это прослойка из фреймворков и библиотек, которые ещё не содержат специфичной бизнес-логики, но уже не являются чистой инфраструктурой. Обычно они языкоспецифичны или привязаны к какой-то технологии. У нас в Яндексе есть userver для C++ (привязка к языку), Flex для BDUI (привязка к технологии), и, собственно, Goliath для Go. Это тот самый слой, наличие которого вызывает больше всего дискуссий. Особенно в мире Go, где в целом не принято использовать большие фреймворки.

Именно об этом «библиотечном» слое, его пользе и цене, которую нужно заплатить за его разработку, я и хочу поговорить дальше.

Зоопарк технологий и досадные инциденты

Чтобы понять, почему мы вообще ввязались в создание Goliath, нужно немного отмотать историю назад. Яндекс Еда не всегда была такой, как сейчас. Когда-то это был стартап Foodfox, написанный на PHP. После того как Яндекс его купил, мы встали перед выбором стека. Был даже заход на Go ещё в 2018 году, но тогда звёзды не сошлись — в том числе, как мне кажется, из-за отсутствия зрелой платформы. Зато в Яндексе уже был мощный фреймворк userver для C++, поэтому большую часть сервисов переписали именно на нём.

Но история циклична. В 2022 году к Еде присоединился Delivery Club. У них тоже был PHP-бэкэнд, который они активно распиливали на микросервисы на Go. В результате мы получили не просто новые команды, а целый парк Go-сервисов без стандартизированных подходов, который был плохо приспособлен к нашей инфраструктуре в Яндексе.

Отсутствие общих корпоративных подходов, периодически приводило к очень неприятным последствиям. Чтобы не быть голословным, приведу пару реальных историй из жизни сервиса.

  • История первая: минус 30% заказов из-за Enum’а. Во время дежурства разработчику прилетает алерт — треть заказов в его сервисе внезапно начали отменяться. Почему? Другой сервис обновил API и добавил новое значение в один из enum. А сервис-потребитель к такому, конечно, был не готов. Но первопричина находилась глубже — отсутствие автоматической кодогенерации клиентов из спецификации API и последующий запуск автоматических тестов. Проблема, которую платформа решает на корню.
  • История вторая: ночной звонок и неработающий сервис. У другого дежурного ситуация была ещё хуже — его сервис просто перестал работать. Совсем. Оказалось, он потерял соединение с базой данных. Наша инфраструктура устроена так, что при сервисных работах мастер в кластере PostgreSQL может меняться. А в коде ребят использовался свой драйвер, который эту смену просто не поддерживал. Если бы они использовали платформенный драйвер, этой проблемы бы не возникло — он обкатан десятками других сервисов и учитывает все особенности нашей инфраструктуры.

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

Так и родилась идея Goliath.

Что такое Goliath и почему симптомы лучше лечить в коде, а не в чатах

Один из главных принципов, который мы заложили в Goliath, — не изобретать велосипед. В мире Go уже есть огромное количество отличных open-source библиотек, и мы не ставили себе цели их переписать заново. Наша платформа — это в основном набор тонких обёрток и утилит, которые адаптируют лучшие инструменты к нашей инфраструктуре и стандартам.

Давайте посмотрим, как это работает на практике, решая те самые проблемы, о которых я говорил.

02 (10).png

Решение для API: кодогенерация

Проблему с рассинхронизацией API, которая привела к потере заказов, мы решили с помощью жёсткой стандартизации и автоматизации.

Всё начинается с одной консольной команды, которая создаёт новый микросервис с полностью готовой структурой проекта. В этой структуре уже есть файлы для спецификации API.

Как только разработчик меняет его — например, добавляет тот самый новый enum — платформа обеспечивает автоматическую перегенерацию кода. Причём не только серверной части, но и всех клиентов, которые используют это API. Любые несовместимые изменения отлавливаются ещё на этапе сборки и тестов, а не в продакшене. Это полностью исключает человеческий фактор в таких вопросах.

В итоге вся рутинная обвязка сервиса стандартизирована, и разработчику остаётся писать только бизнес-логику. При этом проект готов к выкатке в прод с первого коммита.

Решение для инфраструктуры: стандартные драйверы

Проблему с инфраструктурной слепотой, когда сервис не знал об особенностях работы с БД, мы решаем с помощью набора платформенных драйверов.

Например, для работы с PostgreSQL у нас есть библиотека pg — по сути, это обёртка над hasql, которая умеет правильно работать с нашими кластерами, корректно обрабатывает переключение мастера и другие специфичные для нашей инфры вещи. К ней идёт комплементарная txsqlx — такая же обёртка над sqlx для унифицированной работы с транзакциями.

И это касается не только баз данных. У нас есть стандартные драйверы для работы с очередями сообщений (STQ, Logbroker), распределёнными базами данных (YDB, YTsaurus) и другими внутренними инструментами. Каждый такой драйвер аккумулирует в себе весь наш накопленный опыт и лучшие практики работы с конкретным инструментом. Разработчику не нужно думать о тонкостях — он просто берёт готовую библиотеку, которая гарантированно будет работать правильно в нашем окружении.

Что ещё в комплекте?

Goliath — это не только API и базы данных. В нём централизовано решено множество других типовых задач, которые критически важны для микросервисной архитектуры:

  • Наблюдаемость (Observability). Единые подходы к логированию и трейсингу. Когда все сервисы на любом стеке пишут логи и трейсы в одном формате, дебажить кросс-сервисные взаимодействия становится на порядок проще.
  • Надёжность. Стандартные health-чеки, автогенерация дашбордов по метрикам, а также такие сложные механизмы, как deadline propagation и congestion control. Последние вообще не будут работать, если хоть в одном сервисе они реализованы чуть-чуть по-другому. Здесь платформенное решение — единственно возможное.
  • Эксперименты. У нас есть собственная библиотека для проведения A/B-тестов, потому что готовых open source решений, которые бы полностью нас устраивали, мы не нашли.
03 (9).png

По сути, Goliath выступает эдаким проводником в нашу сложную инфраструктуру. Он даёт гарантии, что сервис будет работать стабильно, а разработчик сможет сфокусироваться на бизнес-задачах, а не на решении одних и тех же инфраструктурных проблем раз за разом.

Разработчик — главный клиент вашей платформы

Создать хороший технический инструмент — это только половина дела. Вторая, и, возможно, более сложная и важная половина — сделать так, чтобы им начали пользоваться. Даже самая совершенная платформа бесполезна, если она лежит на полке. И здесь мы столкнулись с тем, что платформу нужно продавать своим же командам — и разработчикам, и продакт-менеджерам.

Работа с сопротивлением

Это может показаться странным, но сопротивление возникает даже со стороны разработчиков, для которых, казалось бы, всё и делается. Аргументы обычно такие: «Мы уже привыкли к своим инструментам», «У меня план по фичам, а тут нужно что-то внедрять», «А вдруг вы там что-то сломаете, а мне это потом разгребать». Это абсолютно нормальная реакция на изменения.

С продактами ещё сложнее. Их мир — это бэклог, фичи и бизнес-метрики. Предложение «давайте потратим время на переход на платформу» звучит для них как «давайте ничего не делать для бизнеса». Они не видят прямой пользы, ведь функциональность самого сервиса от этого не меняется.

04 (8).png

Как с этим работали мы?

Главный аргумент — решение боли. Лучший способ убедить инженера — это показать, как платформа решает его конкретные проблемы. Разговор в духе «а вот если бы был Goliath, тебе бы не пришлось просыпаться ночью из-за упавшей базы» работает гораздо эффективнее любых, даже самых красивых презентаций. Как ни парадоксально, но инциденты становятся лучшими евангелистами платформы.

Общие цели с продуктом. Мы поняли, что навязывать переход «сверху» — провальная стратегия. Вместо этого мы договаривались с продуктовыми командами и начали ставить общие цели. Важно, что они формулировались не как «перейти на платформу», а в терминах бизнеса: «ускорить процесс выкатки на столько-то процентов» или «повысить стабильность сервиса до таких-то показателей». А уже в качестве критериев достижения этих целей был прописан переход на платформу. Это меняет всё: теперь успех продукта напрямую зависит от внедрения платформы, и это становится общей задачей.

Платформа как продукт

Чтобы платформа была востребованной, к ней нужно относиться как к полноценному продукту, а к разработчикам — как к её пользователям. Вот несколько практик, которые мы используем:

  • CustDev и CJM. Мы регулярно общаемся с командами-потребителями, чтобы понять их реальные проблемы. На основе этого мы строим CJM — путь разработчика. Как он создаёт сервис? Как деплоит? Как дебажит? Мы ищем и устраняем затыки и шероховатости на этом пути.
  • Документация и обучение. Без хорошей документации платформа мертва. У нас это must-have. Есть подробные Getting Started гайды, пошаговые мануалы и даже внутренние курсы для новичков. Это очень сильно ускоряет адаптацию.
  • Поддержка с чётким SLA. У разработчика не должно быть страха, что его бросят один на один с проблемой. Для этого у нас работает Support Board — это что-то вроде упрощённого трекера задач, где дежурный из команды платформы обязан ответить на любой вопрос в течение чётко оговорённого времени. Это создаёт ощущение надёжности и доверия.

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

05 (4).png

Платформа — это опыт, зафиксированный в коде

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

Платформа — это самый эффективный способ обмена опытом. Одно дело, когда лучшие практики описаны на вики, и совсем другое — когда они зашиты прямо в код. Если одна команда столкнулась с инцидентом и мы исправили это в платформе, то все остальные команды получают эту защиту автоматически, даже если никогда не знали о первоначальной проблеме. Это превращает все набитые шишки в коллективный иммунитет.

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

Да, продать эту идею бизнесу и даже собственным командам бывает непросто. Но это нужно делать. Потому что в конечном счёте платформа — это то, что даёт разработчикам возможность заниматься действительно важными вещами — создавать ценность для пользователей, а не бороться с инфраструктурой.

  • backend
  • product
  • analytics

Будьте в курсе всех возможностей