Как решить проблему несинхронизированной параллельной разработки в микросервисах
Что проверяют
Понимаете ли вы, как командам менять сервисы независимо и не ломать друг друга на интеграции. Следом обычно спрашивают, как выпустить несовместимое изменение API, не останавливая соседей.
Как отвечать
Суть в том, чтобы договориться о контракте раньше кода и проверять его автоматически:
- contract-first: сначала описание API в OpenAPI, для событий в Kafka схемы Avro или Protobuf. Из спецификации генерируются клиенты и заглушки, и потребитель начинает работу, не дожидаясь реализации;
- контрактные тесты от потребителя: Spring Cloud Contract или Pact. Потребитель фиксирует, какие поля и ответы ему нужны, провайдер прогоняет эти ожидания в своей сборке, и ломающее изменение падает в CI до деплоя;
- обратная совместимость: добавлять поля можно, удалять и переименовывать нельзя. Потребители игнорируют незнакомые поля, в Spring Boot
ObjectMapperтак настроен по умолчанию (FAIL_ON_UNKNOWN_PROPERTIESвыключен); - expand and contract: несовместимое изменение делается в три шага. Добавить новое поле или эндпоинт рядом со старым, перевести потребителей, убрать старое. Для крупных изменений отдельная версия, например
/v2; - реестр схем для событий: Schema Registry в режиме совместимости
BACKWARDне даст опубликовать схему, которую не прочитают текущие потребители; - изоляция в тестах: зависимости поднимаются через Testcontainers или WireMock, а не через общий стенд, который всегда кем-то сломан.
Незаконченное прячется за фиче-флагами, поэтому код сливают в main часто, без долгоживущих веток.
Где спотыкаются
Выносят DTO всех сервисов в общую библиотеку. Любое изменение требует обновить всех разом, и микросервисы превращаются в распределённый монолит.
Полагаются только на end-to-end тесты на общем стенде. Они медленные, нестабильные и ловят несовместимость слишком поздно.
Синхронизируют релизы вручную: «выкатываем пять сервисов одновременно в пятницу». Если сервисы нельзя выпускать независимо, проблема в контрактах, а не в расписании.