API и интеграции

3 мин чтения ·

gRPC: строгий контракт не спасёт от плохой интеграции

Сервисы перестали понимать друг друга после очередного релиза. Поможет ли gRPC или проблему всё равно придётся решать договорённостями команд?

Один сервис передаёт статус заказа, другой его принимает. Поле переименовали, тип уточнили, тесты по отдельности прошли. После релиза склад перестал понимать часть сообщений. На архитектурной встрече появляется предложение: перейти на gRPC, чтобы контракты больше не ломались.

Идея выглядит разумно. gRPC позволяет заранее описать методы и сообщения, часто с помощью Protocol Buffers, и сгенерировать типизированные интерфейсы для клиентов и серверов. Только типизация не означает, что все участники всегда будут совместимы.

Что именно становится строже

Вместо устной договорённости «отправляем объект заказа» команда публикует определение сервиса: какие методы доступны, какие сообщения они получают и возвращают, какие поля ожидаются. Для разработчиков на разных языках из одной схемы можно подготовить клиентские и серверные интерфейсы.

Это уменьшает число случайных расхождений, которые обнаруживаются только при запуске двух сервисов вместе. Контракт удобно проверять и обсуждать до реализации. Но его семантика остаётся предметом договорённости: поле «заказ подтверждён» не объяснит само по себе, оплачено ли оно.

В Protocol Buffers поля идентифицируются номерами. Безопасная эволюция схем требует сохранять смысл уже опубликованных номеров, соблюдать правила совместимости и не переиспользовать удалённые номера как попало. Даже формально корректная схема может сломать бизнес-сценарий, если изменён смысл сообщения. Документация gRPC объясняет модель сервиса и генерацию интерфейсов.

Сеть от строгого контракта не становится надёжнее

Вызов gRPC остаётся удалённым вызовом. Сервис может быть недоступен, ответ — задержаться, соединение — оборваться. Клиенту нужны ограничения времени ожидания, правила повторных попыток и понятное поведение при неизвестном исходе операции.

Представим операцию «зарезервировать товар». Если клиент получил таймаут, резервирование могло уже состояться. Сгенерированный метод не защищает от двойного резерва при повторе. Нужен устойчивый идентификатор бизнес-операции или другой механизм безопасного повторения.

Также нельзя считать, что gRPC автоматически быстрее любого REST API. У него есть эффективные бинарные сообщения и поддержка потоковой передачи, но конечная задержка часто определяется базой, бизнес-логикой и внешними вызовами. Сначала измеряем узкое место, затем меняем транспорт.

Когда streaming помогает делу

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

Но поток требует отдельной дисциплины: что происходит при разрыве соединения, как восстанавливается позиция, как не потерять событие и когда прекращать ожидание. Для обычного запроса одного объекта всё это может оказаться лишним.

Внутренний стандарт не обязан становиться внешним

Для веб-браузеров прямое использование обычного gRPC может потребовать дополнительных решений, например gRPC-Web и прокси. Партнёрам с простым публичным API зачастую удобнее привычный HTTP/JSON-контракт. Компания вправе использовать разные протоколы на разных границах, не превращая их выбор в религиозный спор.

Я бы запросил историю несовместимых релизов: что именно ломалось, чем помогла бы проверка схемы, можно ли автоматизировать контрактные тесты без полной миграции? Если проблема в том, что команды изменяют смысл полей без предупреждения, новый протокол лишь перенесёт эту привычку в другой файл.

gRPC полезен там, где явные внутренние контракты и особенности обмена действительно уменьшают стоимость изменений. Но он не избавляет команды от ответственности за совместимость, ошибки сети и результат операции.