Как вы соблюдали контракты REST API между сервисами, чтобы избежать рассогласования
Что проверяют
Есть ли у вас механизм, который ловит ломающее изменение API до продакшена, или контракт держался на договорённостях и странице Swagger UI. Вопрос про ваш опыт, поэтому ждут конкретики из проекта. Следом спросят, как вы выводили из эксплуатации старую версию.
Как отвечать
Расскажите, как было у вас, опираясь на такие элементы:
- спецификация как источник правды: contract-first, когда OpenAPI лежит в репозитории, а
openapi-generatorплагином Maven или Gradle генерирует интерфейсы контроллеров и клиенты. Или code-first черезspringdoc-openapiс публикацией спецификации при сборке; - проверка совместимости в CI: сравнение новой спецификации с опубликованной (например,
oasdiff), сборка падает на удалённом поле, новом обязательном параметре или сменённом типе; - контрактные тесты: Spring Cloud Contract, где поставщик описывает контракт, а из него получаются тесты для сервера и заглушки WireMock для потребителей. Или Pact, где контракт пишет потребитель, а перед деплоем
can-i-deployчерез Pact Broker проверяет, совместимы ли версии; - правила эволюции: добавлять можно, удалять и переименовывать нельзя. Клиент не должен падать на незнакомых полях (у Jackson за это отвечает
FAIL_ON_UNKNOWN_PROPERTIES, и значение зависит от того, как созданObjectMapper); - версии только для ломающих изменений:
/v2или версия в заголовке, старая живёт с заголовкамиDeprecationиSunset, а по метрикам видно, кто её ещё вызывает.
Цифры нужны ваши: сколько сервисов, сколько инцидентов из-за рассогласования было до и после. Если контрактов у вас не было и всё ломалось, так и скажите и опишите, что внедрили бы первым. Обычно это проверка спецификации в CI как самый дешёвый шаг.
Где спотыкаются
Говорят «у нас был Swagger». Документация показывает контракт, но ничего не проверяет.
Выпускают новую версию API на каждую доработку и годами поддерживают пять параллельных версий.
Считают интеграционные тесты со всеми поднятыми сервисами контрактными. Они медленные, хрупкие и ловят проблему поздно, а добавленное значение enum или поле, ставшее обязательным, всё равно проскакивает.