Обратная совместимость — когда система может работать с более старыми клиентами или потребителями после внесения изменений в интерфейс или формат данных
В интеграциях это критически важно:
если одно приложение изменило контракт, а другое не успело обновиться ➡️ возникает сбой в цепочке бизнес-процессов
▫️ Принцип: поставщик данных эволюционирует без требования изменений от потребителей
Виды совместимостей
⚪️Backward compatibility (обратная) — новые версии совместимы со старыми клиентами
⚪️Forward compatibility (прямая) — старая версия может работать с будущими данными
⚪️Full compatibility (полная) — поддерживаются оба направления
⭐️ Для интеграций чаще всего важна обратная совместимость: не ломать то, что уже работает
Примеры обеспечения обратной совместимости
⚪️Версионирование: явное указание версии контракта через URI, заголовки или параметры
⚪️Добавление новых функций без изменения существующих
⚪️Deprecated-стратегия:
💚сначала поле/метод помечается как устаревший - "deprecated", но остается доступным.
💚через несколько релизов удаляется, после уведомления потребителей
⚪️Контрактное тестирование (Consumer-Driven Contracts): подход к тестированию интеграций, при котором контракт (API, сообщение, схема) формируется не со стороны провайдера, а со стороны потребителя
⚪️Feature flags и поэтапное внедрение:
💚дается потребителям время перейти на новую схему
💚одновременно поддерживаются старый и новый формат
⏩ Обратная совместимость в REST API
Практики:
*️⃣поля в JSON только добавлять, не удалять. Обязательные поля не удалять, а помечать
deprecated*️⃣новые поля делать необязательными (nullable).
*️⃣переименование заменять на добавление нового поля + "депрекейт" старого.
*️⃣версионирование через заголовок "Accept", не нарушает структуру URI.
*️⃣сохранять семантики HTTP-кодов и методов для существующих эндпоинтов
⏩ В gRPC
gRPC использует Protocol Buffers (protobuf)
Он изначально учитывает обратную совместимость
Практики:
➕добавлять новые поля с уникальными номерами тегов
➕делать поля optional
➕не удалять старые поля, помечать их
deprecated➕никогда не менять значения tag-ID
➕при необходимости переименования — объявлять новое поле с новым tag.
➕версионировать proto-файлы (package v1, v2).
⏩ В GraphQL
GraphQL более гибкий, чем REST, так как клиент сам выбирает нужные поля. Но есть риски.
Практики:
⏺использовать директиву
@deprecated вместо удаления. Клиенты будут видеть предупреждение.⏺избегать изменений типов существующих полей
⏺поддерживать старые поля до тех пор, пока все клиенты не перейдут.
⏺для больших изменений — новая схема (например,
/graphql/v2).⏩ В Apache Kafka
Kafka — шина событий. Здесь контракт — формат сообщения.
Если продюсер изменил структуру, все консумеры должны понимать новый формат
Практики:
✨использование Schema Registry для управления схемами
✨применение политик совместимости:
➖backward — новые сообщения читают старые консумеры
➖forward — новые консумеры читают старые сообщения
➖full— поддерживаются оба направления
✨возможность перечитывания исторических данных
✨не менять типы полей
✨не удалять поля без "депрекейта"
✨для критичных изменений — новый топик (
orders.v2)📎 Материалы
1. Обеспечение обратной совместимости gRPC API с помощью protolock в GitHub Actions
2. Постановка проблемы обратной совместимости
3. Интеграции глазами аналитика: 5 типичных ошибок, которые ломают систему
4. Как правильно разрабатывать API с поддержкой обратной совместимости
5. GraphQL: от восторга до разочарования
📚 Книги
API - Сергей Константинов (Раздел III. Обратная совместимость)
🐗 Высоконагруженные приложения. Программирование, масштабирование, поддержка - Мартин Клеппман
#интеграции
➿➿➿➿➿➿➿➿
🧑🎓 Больше полезного в базе знаний по системному анализу