Как улучшить межсерверное взаимодействие и сэкономить время разработчика

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Привет! Я Алексей, Java-разработчик. Хочу поделиться опытом внедрения подхода Contract-First в backend. 

Что такое контракт

Представим продакшн и три группы участников: мобильное приложение, бэкенд и фронтенд.

Кружки на картинке — множество инстансов одного приложения или множество мобильных устройств. Пунктиром показаны HTTP-вызовы. Предположим, два приложения на iOS и Android (зелёные кружки) обращаются к backend (фиолетовые кружки). Это и есть контракты — правила, по которым общаются два участника. 

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

Наш backend — это 60 разработчиков и 100 микросервисов. Мы поддерживаем внутренние и внешние интеграции и катим 50+ релизов в день, большинство — с изменениями контрактов. Согласование контрактов у нас приобретает повышенный уровень сложности. 

Code-First: как мы раньше управляли контрактами

До 2021 года мы использовали Code-First-подход. Описание контракта выглядело так:

@ApiModel(description = "Информация о пользователе")
public class UserInfo {
@ApiModelProperty(value = "Уникальный идентификатор пользователя", required = true)
@NotNull
@JsonProperty("id")
private final String id;
@ApiModelProperty(value = "Имя")
@JsonProperty("firstName")
private final String firstName;
...

Чтобы реализовать HTTP endpoint, мы описывали в Java-коде модели запросов и ответов. Затем помечали их аннотациями Springfox. Классы моделей, запросов и ответов паковали в JAR, а JAR отгружали в Maven Repository. Для каждого микросервиса заводили библиотеку с набором всех контрактов. Для контракта микросервиса profile была библиотека profile-api, для notifer, notifier-api и так далее.

Если одному микросервису нужно было был сходить в другой, он подключал необходимую API-библиотеку к себе в зависимости и использовали её для взаимодействия. Для тех, кто не умеет в Java, у нас был Swagger UI. 

Code-First Swagger UI
Code-First Swagger UI

Это OpenAPI-спецификация, отрендеренная в HTML и сгенерированная по метаданным классов. Так умеет делать Springfox и Springdoc из коробки. Подход достаточно распространен, я часто встречал его в других компаниях. 

Проблемы разработки с Code-First

Если масштабировать Code-First-подход на 100+ сервисов и 60 разработчиков, могут возникнуть проблемы. Давайте их разберём.

Code-First Jar Hell

Представим, что микросервис с именем profile — «коммуникабельный парень». Вот часть его дерева зависимостей на другие API-библиотеки:

+--- yoomoney:profile:2.0.0
| +--- yoomoney:notiifer-api:4.0.0
| | \--- yoomoney:command-api-engine:2.10.1 -> 2.13.1
| +--- yoomoney:cards-api:3.2.0
| | \--- yoomoney:command-api-engine:2.13.1
| +--- yoomoney:content-api:1.0.1
| | \--- yoomoney:command-api-engine:2.10.0 -> 2.13.1
| +--- yoomoney:debt-api:2.0.0
| | \--- yoomoney:command-api-engine:2.13.1
| +--- yoomoney:identifier-api:4.2.0
| | \--- yoomoney:command-api-engine:2.13.1
....

Допустим, мы выпустили новую мажорную версию библиотеки yoomoney:command-api-engine:3.0.0, подключили её в yoomoney:identifier-api:5.0.0 и хотим использовать новое identifier-api в сервисе profile.

Наше новое дерево зависимостей микросервиса profile теперь выглядит так:

+--- yoomoney:profile:2.0.0
| +--- yoomoney:notiifer-api:4.0.0
| | \--- yoomoney:command-api-engine:2.10.1 -> 3.0.0 // конфликт мажорных версий
| +--- yoomoney:cards-api:3.2.0
| | \--- yoomoney:command-api-engine:2.13.1 -> 3.0.0 // конфликт мажорных версий
| +--- yoomoney:content-api:1.0.1
| | \--- yoomoney:command-api-engine:2.10.0 -> 3.0.0 // конфликт мажорных версий
| +--- yoomoney:debt-api:2.0.0
| | \--- yoomoney:command-api-engine:2.13.1 -> 3.0.0 // конфликт мажорных версий
| +--- yoomoney:identifier-api:5.0.0
| | \--- yoomoney:command-api-engine:3.0.0
....

В одну JVM нельзя одновременно загружать несколько разных версий одного класса c совпадающими именами. Если API-библиотеки транзитивно тянут разные мажорные версии зависимостей, будут проблемы в runtime.

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

Изменения API-библиотек в Code-First

На ревью основное внимание уделяется Java-коду, а не контрактам. В идеале нужно проверить согласованность имён, правильность композиции и т.д. На ревью накидывают комментарии в стиле: забыл сделать builder для сущности, не поставил аннотацию. А то, что endpoint уже есть, но называется по-другому, могут пропустить.

Представьте API-библиотеку, в которой 30 endpoint'ов. Разработчик вносит правку в один endpoint или делает новый. На ревью вы не видите общей картины, 29 endpoint'ов ускользнут из поля зрения, из-за этого качество страдает.

Следующая проблема — внесение изменений мобильными разработчиками и фронтендерами. Помню тёмные времена, когда мне говорили: «У нас есть команда с информацией о пользователе, надо немного расширить её ответ, а мы нарисуем красивый UI». Мне приносили JSON-файлик или даже табличку на корпоративной Wiki с описанием endpoint'а

Источник: https://habr.com/ru/company/yoomoney/blog/647441/


Интересные статьи

Интересные статьи

Продолжение перевода AMA от SpaceX. Читать далее
6 августа 1991 года можно считать днём рождения сети Интернет. В этот день Тим Бернерс-Ли запустил первый в мире веб-сайт на первом в мире веб-сервере, доступном по адресу info.cern.c...
Вы знаете, каково это. Впихнуть всё необходимое в спринт и так весьма непросто, а ведь ещё нужно где-то найти дополнительные 10–20% времени разработчиков на возврат технического долга. Если вы ...
Юрий Дзюбан, разработчик программного обеспечения, более девяти лет назад переехал работать в Польшу, а после этого релоцировался в Германию по предложению от Scalors. Сейчас он уже около полугод...
На сегодняшний день у сервиса «Битрикс24» нет сотен гигабит трафика, нет огромного парка серверов (хотя и существующих, конечно, немало). Но для многих клиентов он является основным инструментом ...