Так все-таки RAML или OAS (Swagger)? +19


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



Пост подготовили Анна Мелехова и Владимир Лапатин

Микросервисы. При разработке Acronis Cyber Cloud мы поняли, что нам никуда от них не деться. А проектирование микросервиса невозможно без формализации контракта, который представляет собой интерфейс микросервиса.

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

image
Схема мкросервисов Amazon из твита Вернера Вогелиса, СTO Amazon
В чем же состоит дилемма? Де факто есть два способа взаимодействия микросервисов – HTTP Rest и gRPC от компании Google. Не желая быть вовлеченными в стек технологий Google, мы выбрали HTTP Rest. Аннотации к контрактам HTTP REST чаще всего описываются одним из двух форматов: RAML и OAS, ранее известный как Swagger Поэтому каждая команда разработчиков сталкивается с необходимостью сделать выбор в пользу одного из стандартов. Но, как выяснилось, сделать этот выбор может быть очень непросто.

Зачем нужны аннотации?


Аннотация нужна для того, чтобы внешний пользователь мог легко разобраться, что можно делать с вашим сервисом через его HTTP-интерфейс. То есть на базовом уровне аннотация должна содержать как минимум список доступных ресурсов, их HTTP-методов, тела запросов, перечисление параметров, указание необходимых и поддерживаемых заголовков, а также кодов возврата и форматов ответов. Крайне важным элементом аннотации контракта является и их словесное описание(“что будет, если добавить этот query-параметр к запросу?”, “в каком случае вернется код 400?”)

Тем не менее, когда речь идет о разработке большого количества микросервисов, хочется извлекать дополнительную пользу из написанных аннотаций. Например, на основе RAML/Swagger можно генерировать и клиентский, и серверный код на огромном количестве языков программирования. А еще можно автоматически получать документацию к микросервису и заливать ее на ваш developer-portal :).


Пример структурированного описания контракта

Реже встречается практика тестирования микросервисов на базе описаний контрактов. Если вы написали и аннотацию, и компонент, то можно создать автотест, проверяющий адекватность работы сервиса с различными типами данных на входе. Не возвращает ли сервис код ответа, не описанный в аннотации? Сможет ли корректно обработать заведомо неверные данные?

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

Для работы дополнительных инструментов и RAML, и OAS имеют возможность добавления метаданных, не предусмотренных стандартом (например, так это делается в OAS).

В общем, поле для творчества в применении контрактов для микросервисов — огромное… по крайней мере теоретически

Сравнение ежа с ужом


В настоящее время приоритетное направление разработки в Acronis – развитие Acronis Cyber Platform. Acronis Cyber Platform – это новые точки интеграции сторонних сервисов с Acronis Cyber Cloud и агентской частью. Хотя наши внутренние API, описанные в RAML, нас устраивали, необходимость публикации API опять подняло вопрос выбора: какой же стандарт аннотаций лучше использовать для нашей работы?

Изначально казалось, что решений два — это наиболее распространенные разработки RAML и Swagger (или OAS). Но по факту оказалось, что альтернатив как минимум не 2, а 3 или больше.

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

Но разработчик RAML, компания Mulesoft, присоединилась к консорциуму Open API, который занимается развитием Swagger. Поэтому RAML приостановил свое развитие. Чтобы вообразить формат события представьте, что мейнтейнеры основных компонентов Linux ушли работать в Microsoft. Такая ситуация создает предпосылки для того, чтобы использовать Swagger, который динамично развивается и в последней — третьей версии — практически догоняет RAML по гибкости и функциональности.

Если бы не одно но…


Как оказалось, далеко не все open-source утилиты обновились до версии OAS 3.0. Для микросервисов на Go самым критичным будет отсутствие адаптации go-swagger под свежую версию стандарта. Однако разница между Swagger 2 и Swagger 3 — огромна. Например, в третьей версии разработчики:

  • улучшили описание схем аутентификации
  • доделали поддержку JSON Schema
  • прокачали возможность добавления примеров

Ситуация получается забавная: при выборе стандарта нужно рассматривать RAML, Swagger 2 и Swagger 3 как отдельные альтернативы. При этом только Swagger 2 имеет хорошую поддержку инструментария OpenSource. RAML – очень гибкий… и сложный, а Swagger 3 слабо поддерживаются коммьюнити, так что вам придется пользоваться инструментами собственной разработки или коммерческими решениями, которые, как правило, стоят весьма дорого.

При этом если в Swagger существует много приятных возможностей, таких как готовый портал editor.swagger.io, на который можно загрузить аннотацию и получить ее визуализацию с подробным описанием, ссылками и связями, то для более фундаментального и менее дружелюбного RAML такой возможности нет. Да, можно поискать что-то среди проектов на GitHub, найти там аналог и самостоятельно его развернуть. Однако в любом случае кто-то должен будет поддерживать портал, что не так удобно для базового использования или тестовых нужд. Кроме того, swagger более “беспринципен”, ну или либерален — его можно генерировать из комментариев в коде, что, конечно, идет вразрез с принципом API first и не поддерживается ни одной из утилит RAML,

Мы в свое время начали работать с RAML, как с более гибким языком, и в итоге много должны были делать своими руками. Например, в одном из проектов используется утилита ramlfications в юнит-тестах, которая поддерживает только RAML 0.8. Так что пришлось добавлять костыли, чтобы утилита смогла “кушать” RAML версии 1.0.

А нужно ли выбирать?


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

Для решения этой задачи существует два инструмента OpenSource, которые должны обеспечивать конвертацию контрактов:

  1. oas-raml-converter – ныне неподдерживаемая утилита. В процессе работы с ней мы обнаружили, что у нее возникает ряд проблем со сложными RAML’ами, которые “размазаны” по большому количеству файлов. Эта программа написана на JavaScript и выполняет рекурсивный обход синтаксического дерева. Из-за динамической типизации разобраться в этом коде становится сложно, так что мы решили не тратить время на написание патчей к умирающей утилите.
  2. webapi-parser — инструмент от той же компании, который претендует на готовность конвертировать все и вся, причем в любую сторону. На сегодняшний день заявлена поддержка RAML 0.8, RAML 1.0 и Swagger 2.0. Однако на момент нашего исследования утилита была еще КРАЙНЕ сырой и непригодной для использования. Разработчики создают своего рода IR, что позволит им в будущем быстро добавлять новые стандарты. Но пока все это просто не работает.

И это еще не все сложности, с которыми мы столкнулись. Одним из шагов нашего пайплайна является проверка того, что RAML из репозитория является корректным относительно спецификации. Мы перепробовали несколько утилит. Удивительно, но все они ругались на наши аннотации в разных местах и совершенно разными дурными словами. Причем не всегда по делу :).

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

Заключение


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

Определить набор инструментов, которые вы будете использовать позже. Например, если вам нужно просто отображать контракт, проще будет использовать Swagger 2, у которого есть красивый API, ведь в RAML вам придется поднимать и поддерживать сервис самостоятельно.
Чем больше будет у вас задач, тем шире будет потребность в инструментах, а они разные для разных платформ, и лучше сразу ознакомиться с доступными версиями, чтобы сделать выбор, минимизирующий ваши затраты в будущем.

Но стоит признать, что все экосистемы, существующие на сегодняшний день, несовершенны. Поэтому если в компании есть фанаты, которые любят работать в RAML, потому что “он позволяет более гибко выражать мысли”, или, наоборот, предпочитают Swagger, потому что “он понятнее”, — лучше всего оставить их работать в том, в чем они привыкли и хотят, потому что инструментарий любого из форматов требует доработки напильником.

Что касается нашего опыта, в следующих постах мы расскажем о том, какие — статические и динамические проверки мы проводим на базе нашей RAML-Swagger архитектуры, а также о том, какую документацию мы генерируем из контрактов, и каким образом все это работает.




К сожалению, не доступен сервер mySQL