Эмиль Воге, CEO компании Traefik Labs, приводит на портале The New Stack пять антипаттернов, охватывающих наиболее распространенные практики API-менеджмента.

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

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

Некоторые сервисы основаны на Java, «защищены» старыми сертификатами TLS 1.1 и находятся за политикой контроля доступа JWT. Другие сервисы основаны на Python, используют сертификаты TLS 1.3 и находятся за пользовательской политикой управления доступом. Это разнообразие распространяется и на остальные службы в вашей производственной среде.

Вы (обоснованно) считаете, что ситуация далека от идеальной, и планируете рационализировать API в DonutGPT с помощью решения для API-менеджмента. Ваши требования включают:

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

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

Похоже, что ваш план верен, и вы на пути к лучшим дням (или ночам). Однако путь к API-менеджменту долог, и на нем много препятствий. Вот пять худших антипаттернов, которых вам следует избегать, когда вы начинаете свою API-одиссею.

Антипаттерн 1. Монолитный подход к микросервисам

Вы собираетесь инвестировать время, деньги и усилия в развертывание решения для управления API. В ходе этого процесса вы централизуете многие аспекты ваших открытых сервисов, такие как управление трафиком, безопасность соединений и наблюдаемость. При этом легко подумать, что «чем больше все централизовано, тем больше у меня контроля и тем лучше я буду спать». Почему бы не использовать решение для управления API для перехвата каждого вызова API и преобразования тела HTTP для очистки его от конфиденциальных данных (например, частной информации)?

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

Давайте перенесемся на три года вперед. Ваша платформа API-менеджмента стала зрелой и управляет сотнями API в десятках различных команд. Первоначальная быстрая победа по очистке тела HTTP в рамках рабочего процесса API-менеджмента постепенно превратилась в «белого слона» (казалось бесплатно и выгодно, но оказалось дорого и бесполезно):

  • Первое быстрое обновление неизбежно привело к усложнению требований, которые необходимо было адаптировать к каждому API. Ваши десять стильных строк кода быстро превратились в неподъемный скрипт на 5000 строк.
  • Никто не хочет брать на себя ответственность за этот пользовательский скрипт теперь, когда он работает с API многих команд.
  • Каждая новая версия API может потребовать обновления и тестирования этого куска кода, который находится в платформе API и отделен от репозиториев кода сервисов.
  • Тестирование этого пользовательского скрипта требует много работы. Если у вас возникнут проблемы, вы узнаете о них в первую очередь из живого трафика, и вам будет сложно отладить его.
  • Ваше API-решение очень ресурсоемкое. Вам не следует делегировать все тело HTTP обратному прокси. Это потребляет большую часть процессорных ресурсов, выделенных для вашей платформы, что дает очень мало возможностей для обеспечения безопасности и делает этот подход очень дорогим.

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

Разделение функций имеет решающее значение при разработке следующей производственной платформы.

Антипаттерн 2. Телега впереди лошади

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

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

Перенесемся на три года вперед с этим первоклассным и дорогим решением:

  • Переход с устаревшей платформы занял гораздо больше времени, чем ожидалось.
  • Новое решение потребовало платных тренингов от поставщика для вашей команды и многих разработчиков по всей компании.
  • Использование многих функций решения по-прежнему только в перспективе.
  • Многие команды разработчиков избегали перехода на новую платформу из-за ее сложности.
  • Ваша первоначальная цель — контролировать все вызовы API в компании — до сих пор не достигнута.
  • Вы все еще не высыпаетесь.

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

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

Вот пример постепенного внедрения того же самого продукта:

  1. Начните с малого — с базовых Ingress-ресурсов на Kubernetes.
  2. Затем будет внедрен API-шлюз, который обеспечит управление трафиком API и безопасность.
  3. Далее, когда вы будете лучше понимать, какие функции важны для вашего бизнеса, переходите к платформе управления API.

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

Не забегайте вперед при переходе на платформу управления API.

Антипаттерн 3. Почти IaC — это достаточно хорошо

Как современный руководитель отдела платформенного инжиниринга, вы твердо верите в модель «инфраструктура как код» (IaC). Управление и предоставление ресурсов в декларативных конфигурационных файлах — это современный и отличный шаблон проектирования для снижения затрат и рисков. Естественно, вы заложите эту основу при проектировании своей инфраструктуры.

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

Или, что еще хуже, ваш продукт для управления API должен обеспечивать согласованный пользовательский IaC-опыт. Некоторые компоненты необходимо настраивать в пользовательском интерфейсе. Некоторые компоненты используют YAML, другие — XML, у вас есть даже проприетарные форматы конфигурации. Такие разные подходы делают невозможным согласованный процесс.

Вы говорите себе: «Инфраструктура как код — это здорово, но исключения — это нормально. Почти IaC — это достаточно хорошо».

Перенесемся на три года вперед:

  • 60% инфраструктуры полностью объявлено в конфигурационных файлах и размещено в git-репозитории.
  • Эти конфигурационные файлы написаны в пяти форматах: YAML, INI, XML, JSON и пользовательский формат.
  • Оставшиеся 40% требуют ручных операций в некоторых инструментальных панелях или файлах.
  • Форматы или процессы конфигурирования настолько разнообразны, что ваша команда не может взять платформу под контроль и постоянно нуждается в помощи других команд, которые знают отдельные форматы или процессы.
  • Роль человеческого фактора настолько высока, что процесс выпуска релизов затягивается и становится ненадежным. Любое изменение в инфраструктуре требует нескольких дней для развертывания в производстве, и это в лучшем случае.
  • В худшем случае изменение, развернутое в производстве, приводит к серьезному сбою. Поскольку ваша команда не в состоянии быстро устранить неполадки, время восстановления измеряется часами. Ваш начальник с тревогой смотрит на экран через ваше плечо, ожидая, когда же будет развернуто чудесное исправление. Тысячи заказов пончиков будут упущены.
  • Вы даже не пытаетесь заснуть этой ночью.

Вывод очевиден — настройка API-менеджмента частично как кода не соответствует цели снижения затрат и рисков. Только когда ваше решение по управлению API на 100% основано на коде, вы можете получить преимущества надежной платформы, быстрого выхода на рынок и быстрого восстановления.

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

Никогда не соглашайтесь на половинчатые процессы.

Антипаттерн 4. Хаотичная система версионирования

Когда вы только начинаете свой API-путь, спланировать и предугадать все сценарии использования очень сложно. Перемены неизбежны, но не то, как вы ими управляете. Как мы увидим в этом разделе, последствия плохого управления изменениями могут нарастать как снежный ком с годами.

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

По прошествии одного года ваш современный мониторинг заваливает вас уведомлениями, указывая на кучу вызовов API от одного из ваших крупнейших клиентов с ошибками 404. Ошибки 404 широко распространены, поэтому вы не обращаете на них внимания и быстро передаете проблему команде разработчиков, отвечающей за этот API.

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

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

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

  • Некоторые команды не утруждали себя проверкой совместимости и продолжали вносить критические изменения.
  • Некоторые команды пытались любой ценой сохранить обратную совместимость своих API. Это не только превращало кодовую базу в кошмар для поддержки, но и постепенно становилось очевидным, что это отбивало у команд желание внедрять инновации, поскольку они хотели избежать внесения изменений и поддерживать совместимость со всеми версиями.
  • Некоторые команды придерживались более надежного процесса, используя URL-версионирование, например https://donutgpt.com/v1/donuts и https://donutgpt.com/v2/donuts. Они могли поддерживать несколько версий одновременно, с разными кодовыми базами для каждой версии. Проблема заключалась в том, что другие команды использовали другие стратегии, например, версионирование параметров запроса (https://donutgpt.com/donuts?version=v1) или даже версионирование заголовков.
  • Некоторые команды последовательно придерживались определенной стратегии версионирования, например URL-версионирования, но не предоставляли версионированную документацию.

Это исследование заставляет нас осознать, насколько креативен человеческий мозг — разработчики выбрали так много различных вариантов!

В результате клиенты были вынуждены:

  • использовать устаревшую документацию;
  • вызывать устаревшие или неработающие API;
  • вызывать разные API с разными стратегиями версионирования;
  • вызывать ненадежные API;
  • получать пончики с вашим новым «экспериментальным рецептом», когда заказывали классический «Legend GPT Donut».

Основные выводы очевидны: никакой код не вечен, а изменения — естественная часть разработки API. Учитывая эту истину, вы должны иметь прочную, надежную и повторяемую основу для процесса выпуска и управления жизненным циклом API.

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

Кроме того, убедитесь, что команды поддерживают несколько версий своих API, которые могут быть легко доступны в рамках более широкой передовой практики управления изменениями. Только так можно обеспечить постоянный и надежный пользовательский опыт для ваших клиентов.

Применяйте единую стратегию версионирования для всех ваших API.

Антипаттерн 5. Управление зависимостями в стиле YOLO («ты живешь только один раз»)

Теперь, когда вы узнали, почему управление стратегией версионирования API очень важно, давайте обсудим управление зависимостями для API — тему, которую часто недооценивают по вполне понятной причине. Она довольно продвинутая.

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

Спустя еще два месяца ваш современный мониторинг снова предупреждает вас о нескольких вызовах API от одного из ваших крупнейших клиентов, которые приводят к ошибкам 404! Это что, шутка! Вы знаете продолжение истории: рабочая группа, устранение неполадок, TooManyDonutsErrors, анализ первопричины и (барабанная дробь) ...

Все ваши API действительно следовали принудительной стратегии версионирования: https://donutgpt.com/v1/donuts. Так что же произошло?

Это было сделано только для опубликованных на платформе управления API маршрутов. Сервисы, стоящие за API, следовали другой стратегии версионирования. И даже для этих всего нескольких сервисов не было управления зависимостями между API-маршрутами и бэкенд-сервисами.

Другими словами, сайты https://donutgpt.com/v1/donuts и https://donutgpt.com/v2/donuts могли вызывать одну и ту же версию сервиса, что приводило к ситуации, похожей на эпизод с отсутствием стратегии версионирования, с ужасным клиентским опытом. Все становится еще сложнее, если одни сервисы вызывают другие сервисы.

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

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

Обеспечьте проверку зависимостей при развертывании.

Подведение итогов

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

Вы гордитесь тем, что являетесь частью этой истории успеха; однако, несмотря на ускорение темпов развития, компания теперь сталкивается с более сложными проблемами. Самая большая проблема, безусловно, заключается в индустриализации API DonutGPT, используемых клиентами и реселлерами. На этом пути вы перепробовали множество решений, начали все сначала, приняли несколько отличных решений... и несколько спорных. DonutGPT перепутала несколько заказов на пончики, пока исследовала мир API.

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

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

Планируя свое API-путешествие, вы должны учитывать эти пять принципов, чтобы получить максимальную отдачу и свести к минимуму усилия:

  • Проектируйте платформу API с четким разделением функций. Избегайте делегирования бизнес-логики платформе.
  • Не устанавливайте слишком высокую планку или слишком быстрые дедлайны. Действуйте шаг за шагом. Начните с более простых концепций, таких как ингрессы, и постепенно переходите к более сложным сценариям использования API, когда вы лучше их поймете.
  • При индустриализации процессов терпимое отношение к исключениям приведет к недостижению цели, и вы не получите всех ожидаемых преимуществ полностью автоматизированной платформы.
  • Версионирование является критической проблемой в долгосрочной перспективе. Если вы начнете свой API-путь с сильной и последовательной стратегии версионирования для всех API, ваша платформа будет более масштабируемой, надежной и предсказуемой.
  • В сложных инфраструктурах с множеством отдельных частей контроль и сертификация зависимостей для всех компонентов имеет решающее значение для достижения высокого уровня доверия и стабильности вашей платформы.

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