При проектировании интеграций вы выбираете не только «какие системы связать», но и как клиент будет ждать ответ. REST, gRPC и GraphQL — три распространённых способа построить синхронный request–response; в заголовке они названы «протоколами» для краткости, хотя REST — архитектурный стиль, gRPC — RPC-фреймворк, GraphQL — язык запросов и runtime. Фокус статьи — unary-вызов (один запрос → один ответ); streaming и subscriptions затронуты с оговорками. Статья помогает зафиксировать различия в спецификации, выбрать подход по контексту и не смешивать синхронный вызов с длинными бизнес-процессами.
1. Суть темы
Синхронное взаимодействие в интеграции — паттерн, при котором вызывающая сторона отправляет запрос и ожидает ответ в рамках одного логического вызова (request–response). Клиент блокируется или логически «висит» до получения результата, ошибки или таймаута. Это контрастирует с асинхронной доставкой через очереди и события, где ответ приходит позже и по другому каналу.
REST, gRPC и GraphQL — основные современные способы построить синхронный API:
| Подход | Суть для аналитика | Транспорт и формат |
|---|---|---|
| REST | Архитектурный стиль поверх HTTP: ресурсы, URI, методы, представления | HTTP/1.1–2, чаще JSON |
| gRPC | RPC-фреймворк со строгим контрактом в Protocol Buffers | HTTP/2, бинарная сериализация |
| GraphQL | Язык запросов и runtime: одна схема, клиент выбирает поля | HTTP (обычно POST), JSON |
В корпоративных ландшафтах (банки, гос, ERP) по-прежнему встречается SOAP и XML-RPC как синхронный legacy — см. 07.02 Принципы работы HTTP, REST, SOAP и 10.01.05 Шаблон спецификации SOAP API; в этой статье они не сравниваются детально, но учитывайте их при инвентаризации интеграций.
Scope статьи: unary REST/gRPC и query/mutation GraphQL. Server/client/bidirectional streaming gRPC и GraphQL subscriptions — полусинхронные или длинные сессии; на sequence diagram помечайте их отдельно от классического round-trip.
Граница этой статьи:
| В зоне этой статьи | Вынесено в соседние заметки |
|---|---|
| Сравнение REST, gRPC, GraphQL; выбор подхода; что фиксировать в спецификации | Форматы контрактов OpenAPI, Protobuf, GraphQL SDL — 03.05.03 Спецификации контрактов (OpenAPI, AsyncAPI, Protobuf) |
| Синхронный request–response | Асинхронные каналы, события, polling — 03.05.04 Асинхронное взаимодействие (очереди, Kafka, Events) |
| Подход как слой интеграции | Архитектура интеграции (точка-точка, ESB, API-led) — 03.05.01 Виды интеграции (точка-точка, ESB, API-led) |
| Теория HTTP и семантика REST | 07.02 Принципы работы HTTP, REST, SOAP |
| Практика ручной проверки API | 07.02 Работа с API (практика) |
| Детали REST + OpenAPI | 03.05.02 REST и OpenAPI спецификации |
| Углублённо gRPC и GraphQL как контрактное программирование | 03.05.04 Контрактное программирование и протоколы (gRPC, GraphQL) |
| OAuth2, JWT, threat model, mTLS | 03.05.05 Безопасность API |
| Детали rate limiting, pagination как NFR | 03.06.03 Rate Limiting — управление пропускной способностью, 08.02 Нефункциональные требования (НФТ) — классификация и стандарты |
sequenceDiagram
participant Client as Клиент
participant API as API (REST / gRPC / GraphQL)
participant Backend as Backend / БД
Client->>API: Запрос (синхронный, unary)
Note over Client,API: Клиент ждёт ответ или таймаут
API->>Backend: Обработка
Backend-->>API: Данные / ошибка
API-->>Client: Ответ (2xx / 4xx / 5xx или gRPC status)
Подход к API — лишь один слой интеграционного интерфейса. Вместе с ним в 03.01.04 Интерфейсы и интеграционные взаимодействия вы описываете форматы сообщений, политики безопасности, SLA и идентификаторы корреляции.
2. Ключевые понятия
Синхронный вызов и API-контракт
API (Application Programming Interface, программный интерфейс приложения) — формальный контракт между системами: операции, структуры данных, коды ошибок, правила аутентификации. В синхронной модели контракт определяет один запрос → один ответ (или явный таймаут/ошибку сети).
Критерии, по которым на проекте отличают синхрон от асинхронного канала:
- Клиент не продолжает основной сценарий без ответа (или без явного fallback).
- Нет промежуточного буфера доставки (очередь, топик) между запросом и ответом в рамках одного логического вызова.
- SLA по latency задаётся на один round-trip, а не на end-to-end процесс.
Пограничный случай: в ESB-ландшафтах синхронный request–reply через message broker (клиент ждёт ответ в том же сеансе, но транспорт — очередь) формально sync для вызывающего, но архитектурно ближе к модели интеграции через шину — фиксируйте это явно в матрице потоков.
Webhooks и callbacks — исходящий HTTP POST партнёру после события: инициатор не ждёт ответ в своём пользовательском сценарии (хотя HTTP-вызов технически request–response). Это не классический sync API из scope статьи; длинные процессы с опросом статуса или callback — см. 03.05.04 Асинхронное взаимодействие (очереди, Kafka, Events).
Доменное событие как триггер sync-вызова — частый паттерн в событийной архитектуре: CRM публикует «заказ создан», Billing синхронно вызывает сервис расчёта в рамках обработчика. Канал остаётся request–response, хотя инициатор — реакция на событие; в матрице потоков фиксируйте и триггер, и тип канала отдельно.
REST (Representational State Transfer)
REST — архитектурный стиль, а не единый стандарт «REST API». Для аналитика важны не все ограничения Fielding, а то, что попадает в контракт:
- Ресурсы с URI (
/orders/{id}) и HTTP-методы с семантикой операций (GET — чтение, POST — создание, PUT/PATCH — изменение, DELETE — удаление). - Представления — JSON/XML как снимок состояния ресурса; статус-коды HTTP — сигнал успеха или ошибки.
- Идемпотентность методов — GET, PUT, DELETE безопасны для повтора; POST — нет, если не задокументирован
Idempotency-Key.
Детали HTTP-семантики, кэширования, conditional requests и multipart — в 07.02 Принципы работы HTTP, REST, SOAP; контракт de facto описывают в OpenAPI — 03.05.03 Спецификации контрактов (OpenAPI, AsyncAPI, Protobuf) и 03.05.02 REST и OpenAPI спецификации.
gRPC (Google Remote Procedure Call)
gRPC — фреймворк удалённого вызова процедур (RPC) с контрактом в Protocol Buffers (protobuf). Транспорт — HTTP/2, сериализация — бинарная (контекст — 07.07 Сетевые основы (подсети, протоколы и маршрутизация)).
В scope статьи — unary: один запрос, один ответ. Streaming-режимы (server/client/bidirectional) — полусинхронные сессии; на диаграммах помечайте отдельно. Структура .proto (service, rpc, messages) — 03.05.03 Спецификации контрактов (OpenAPI, AsyncAPI, Protobuf); углублённо — 03.05.04 Контрактное программирование и протоколы (gRPC, GraphQL).
Сильные стороны для SA: строгая типизация, contract-first, генерация клиентов. Для браузера и внешних партнёров обычно нужен grpc-web или API-gateway с трансляцией в HTTP/JSON.
GraphQL
GraphQL — язык запросов и runtime: одна HTTP-точка, схема (schema) как контракт (types, queries, mutations). Клиент задаёт форму ответа — снижается over-fetching; тот же эффект частично даёт BFF + узкие REST-endpoint'ы.
Для спецификации фиксируйте: resolver → backend-сервис, лимиты сложности запроса, поддержку batching. Mutations — синхронные изменения; subscriptions (WebSocket) — вне классического request–response. Governance схемы — 03.05.04 Контрактное программирование и протоколы (gRPC, GraphQL).
Частичный успех: HTTP 200 + блок data и errors[] одновременно — отдельный сценарий приёмки; клиент должен обрабатывать оба блока, в отличие от REST (код 4xx/5xx) и gRPC (status ≠ OK).
Сравнение для принятия решения
| Критерий | REST | gRPC | GraphQL | Что зафиксировать в SRS/NFR |
|---|---|---|---|---|
| Модель контракта | Ресурсы + HTTP-семантика | Service + rpc + messages | Schema: types, queries, mutations | Ссылка на machine-readable контракт как источник правды |
| Типичный потребитель | Браузер, B2B, legacy | Микросервисы backend-to-backend | BFF, SPA, агрегирующий слой | Класс потребителя → выбор auth и SLA |
| Кэширование | HTTP-кэш, ETag | На уровне приложения | Ограничено; complexity limits | Политика кэша или явное «без кэша» |
| Версионирование | URL, заголовки | Совместимость полей в proto | Deprecate полей в схеме | Политика breaking changes — 03.05.07 Управление версионированием API и жизненным циклом |
| Контракт ошибок | HTTP-код + RFC 7807 | gRPC status + details | errors[], частичный успех | Таблица кодов/типов + сценарии retry |
| Отладка без tooling | curl, Postman | grpcurl, reflection | GraphiQL | Нужен ли sandbox/мок для приёмки |
3. Как применяется в работе аналитика
Фиксация подхода в архитектурном контексте
На диаграмме контекста и при декомпозиции для каждого интеграционного потока зафиксируйте:
- Кто вызывает кого (внутренний/внешний потребитель).
- Подход (REST / gRPC / GraphQL) и формат payload — см. 07.03 Основы XML, JSON, YAML.
- Синхронный vs асинхронный канал — не смешивайте на одной стрелке без пояснения.
- SLA: latency (p95), availability, допустимые таймауты и retry.
Пример строки матрицы интеграций. Колонка «Триггер» — что инициирует вызов (событие, действие пользователя, расписание); триггер ≠ тип канала: «sync-вызов по событию» означает, что обработчик доменного события ждёт ответ в том же потоке, а не что канал асинхронный.
| Источник | Потребитель | Подход | Операция | Триггер | SLA latency |
|---|---|---|---|---|---|
| CRM | Billing | gRPC | OrderService.CreateInvoice | создание заказа (sync-вызов по событию из 03.05.06 Event-Driven Architecture) | < 500 ms |
| Mobile App | BFF | GraphQL | query orderDetails | действие пользователя | < 800 ms |
| Partner | Public API | REST | POST /v1/shipments | запрос партнёра, до 100 rps | < 1 s |
Цепочки синхронных вызовов и latency budget
Типичная цепочка: UI → BFF → сервис A → сервис B. На sequence diagram указывайте не только SLA одного hop, но и суммарный e2e-бюджет:
- Задайте end-to-end p95 для сценария (например, 1,2 s для экрана заказа).
- Распределите бюджет по hop'ам — каждый участник цепочки получает долю с запасом на сеть и сериализацию; сумма hop'ов ≤ e2e.
- Timeout вызывающей стороны на hop N должен покрывать worst-case downstream на этом hop с учётом retries: timeout(A→B) ≥ p99(B) × (1 + число retry) + запас на сеть. Пример: p95 сервиса B = 400 ms, допускается 2 retry → timeout A не может быть 400 ms — нужен запас под три попытки (≈ 1,2 s + overhead).
- Timeout на hop N при этом ≤ оставшемуся e2e-бюджету после предыдущих hop'ов — иначе цепочка «съест» SLA экрана.
Не путайте: SLA downstream — обещание сервиса; timeout клиента — сколько вызывающий готов ждать на этом hop. Timeout обычно ≥ SLA downstream (с запасом на retry), но ≤ доля e2e для данного участка.
При превышении бюджета — сокращение цепочки (агрегация в BFF), кэш или переход на асинхронный канал.
Моделирование на диаграммах поведения
На sequence diagram явно указывайте тип вызова и синхронное ожидание:
- REST:
GET /orders/{id},POST /orders+ ожидание200/201/4xx. - gRPC:
OrderService.GetOrder(request)+ gRPC statusOK/NOT_FOUND(unary). - GraphQL:
query GetOrder { order(id: ...) { ... } }+ блокerrorsв JSON-ответе; отдельный alt-поток для частичного успеха (200 +data+errors).
Для прецедентов добавьте альтернативные потоки: таймаут, 503, retry (только для идемпотентных операций — GET/PUT/DELETE или POST с Idempotency-Key), fallback на кэш или асинхронный сценарий.
Связь с моделью данных
Каждое поле запроса и ответа трассируйте к логической модели и словарю данных: тип, обязательность, источник истины, правила преобразования.
| Подход | Что включать в спецификацию интерфейса |
|---|---|
| REST | Таблица endpoints; ссылка на OpenAPI; маппинг JSON-полей на сущности |
| gRPC | Перечень services, rpc, messages, enum из .proto; коды gRPC status |
| GraphQL | Фрагмент схемы (types, queries, mutations); какой resolver читает какой backend |
При GraphQL или BFF критично согласовать источник истины для каждого поля: одно поле в схеме может агрегировать данные из нескольких сервисов — это должно быть видно в спецификации, иначе расходится с ER-моделью.
Выбор подхода: практические критерии
Значимое решение оформляйте в ADR: контекст, альтернативы, последствия для потребителей и NFR. Breaking change в контракте согласуйте по процессу из 03.05.07 Управление версионированием API и жизненным циклом и 02.05.05 Жизненный цикл требования — до правки OpenAPI/proto/schema, а не после релиза.
REST + OpenAPI — когда:
- публичный или партнёрский API с широкой аудиторией и ожиданием «стандартного HTTP»;
- простые CRUD-операции над ресурсами;
- нужна максимальная совместимость с HTTP-экосистемой и legacy;
- gRPC/GraphQL снаружи допустимы через API gateway с трансляцией в REST/JSON.
gRPC — когда:
- низкая задержка и высокая пропускная способность между внутренними сервисами;
- нужен строгий contract-first и генерация кода из
.proto; - unary покрывает сценарий; streaming — осознанное расширение контракта.
GraphQL — когда:
- агрегирующий слой (BFF, публичный или внутренний) обслуживает UI с разными наборами полей (web, mobile);
- over-fetching широких REST-ресурсов создаёт измеримую проблему, а BFF с узкими endpoint'ами нецелесообразен;
- команда готова к governance схемы.
Если сценарий длится секунды и минуты (оркестрация, комплаенс-проверки), не растягивайте синхронный вызов: используйте 202 Accepted + polling/callback/webhook, либо асинхронный канал.
flowchart TB
subgraph choice [Выбор подхода]
Q1{Внешний / публичный API?}
Q2{Нужна агрегация полей под UI?}
Q5{Внутренний BFF / агрегирующий слой?}
Q3{Низкая latency между сервисами?}
Q4{Прямой HTTP без gateway?}
end
Q1 -->|да| Q2
Q1 -->|нет, внутренний контур| Q5
Q2 -->|да| GraphQL
Q2 -->|нет| Q4
Q4 -->|да| REST
Q4 -->|нет: gRPC/GraphQL за gateway| GW[Gateway → REST/JSON наружу]
Q5 -->|да| GraphQL
Q5 -->|нет, прямой service-to-service| Q3
Q3 -->|да, unary sync| gRPC
Q3 -->|нет| REST
Нефункциональные требования: чеклист для спецификации
В спецификации интерфейса зафиксируйте минимум, без дублирования смежных статей — детали безопасности в 03.05.05 Безопасность API, классификация NFR в 08.02 Нефункциональные требования (НФТ) — классификация и стандарты, rate limiting в 03.06.03 Rate Limiting — управление пропускной способностью:
- Аутентификация и авторизация — механизм на уровне контракта (OAuth2, JWT, API Key; gRPC metadata, mTLS).
- Rate limiting и pagination — есть/нет, формат (REST: cursor/offset; GraphQL: connections).
- Идемпотентность — REST: семантика GET/PUT/DELETE (безопасный retry) vs POST +
Idempotency-Key; gRPC: ключ в metadata или документированная семантика unary-вызова; GraphQL: уникальные input id, dedup на сервере. - Таймауты и retry — retryable-коды (429, 503 +
Retry-After); на каждом hop: timeout ≥ worst-case downstream × (1 + retries), сумма hop'ов ≤ e2e-бюджет (см. раздел выше). - Observability — correlation id / trace id (REST: заголовки; gRPC: metadata; GraphQL: extensions).
- Версионирование — политика breaking changes: 03.05.07 Управление версионированием API и жизненным циклом.
Полный NFR-раздел удобно оформить по 10.01.12 Шаблон нефункциональных требований (NFR).
Артефакты, которые вы отдаёте команде
Минимальный набор для синхронного интерфейса (связь с форматами требований):
- Таблица операций — имя, method/query/rpc, вход, выход, коды ошибок, идемпотентность.
- Machine-readable контракт (OpenAPI /
.proto/ GraphQL SDL) как единственный источник правды; таблица в Confluence — производная, со ссылкой на репозиторий контракта. - Матрица интеграций — система → система, подход, объём, SLA, latency budget для цепочек.
- Критерии приёмки — воспроизводимые сценарии по 02.04.02 Критерии приёмки (Acceptance Criteria); проверка на стенде — 07.02 Работа с API (практика); для REST — 10.01.04 Шаблон спецификации REST API.
- Contract / consumer-driven тесты (Pact и аналоги) — мост между контрактом и V&V / 08.03 Тестирование требований (статическое тестирование); в SRS зафиксируйте роль аналитика как владельца контракта (согласование breaking change, актуальность спецификации), а consumer/provider — ответственность команд разработки.
4. Типовые ошибки и ограничения
Ограничения подходов
REST:
- «REST на бумаге» vs фактический RPC через
POST /doSomething— нарушается единообразие интерфейса, усложняется кэширование и документирование. - Over-fetching и under-fetching — частично решается BFF и узкими ресурсами, не только GraphQL.
- Версионирование без дисциплины — расхождение URL, заголовков и тела между средами.
gRPC:
- Высокий порог для внешних партнёров и аналитиков без специализированного tooling.
- Бинарный контракт усложняет ручную отладку; нужны grpcurl, reflection, сгенерированная документация.
- Для браузера и части legacy — обязателен gateway; это отдельный компонент в архитектуре.
- Streaming в контракте ≠ «ещё один sync endpoint» — иная модель таймаутов и backpressure.
GraphQL:
- Тяжёлые запросы — глубокая вложенность, N+1 на resolver'ах; governance — в 03.05.04 Контрактное программирование и протоколы (gRPC, GraphQL).
- Сложность HTTP-кэширования — кэш на уровне CDN/прокси работает иначе, чем у REST GET.
- Размывание ответственности: frontend может «собрать» запрос, который неожиданно нагружает backend.
- Subscriptions — отдельная инфраструктура (WebSocket), не путать с простым синхронным query/mutation.
Типичные ошибки аналитика
| Ошибка | Последствие | Что делать |
|---|---|---|
| Синхронный API для длинного процесса | Таймауты, блокировка UI, потеря транзакций | 202 + async, очередь, polling, webhook |
| Нет контракта ошибок | Несогласованная обработка на клиентах | REST: RFC 7807; gRPC: status + details; GraphQL: errors[] и сценарий частичного успеха |
| Таблица в Confluence вместо OpenAPI/proto | Устаревшая спецификация, расхождение со стендом | Machine-readable контракт в репозитории — источник правды |
| GraphQL «на всё» без лимитов | Деградация production | Complexity budget, persisted queries, review схемы |
| Игнорирование идемпотентности POST/mutation | Дубликаты при retry | Idempotency-Key (REST), metadata/input id (gRPC/GraphQL) |
| Разные модели в REST и gRPC без маппинга | Расхождение с ER и словарём данных | Единая логическая модель, явный mapping |
| Протокол выбран «модно», без NFR | Не выполняются latency и availability | Критерии выбора + ADR + нагрузочные допущения |
| Не указаны таймауты и budget на sequence diagram | Неверные ожидания интеграции | Timeout/retry по hop, e2e-budget; circuit breaker — 03.06.01 Архитектурные паттерны распределённых систем |
| Путаница webhook / события с sync API | Неверная модель ожиданий клиента | Webhook — исходящее уведомление; sync по событию — обработчик ждёт ответ; см. 03.05.06 Event-Driven Architecture |
Синхронный вызов не заменяет согласованность данных между системами: при сбое после ответа «успех» нужны компенсирующие действия или асинхронное подтверждение — это предмет асинхронных паттернов и 03.06.01 Архитектурные паттерны распределённых систем.
Связи с другими разделами базы
- Интеграционный контекст и интерфейсы — 03.01.04 Интерфейсы и интеграционные взаимодействия, 03.01.02 Моделирование контекста системы (Context Diagram)
- Виды и архитектура интеграции — 03.05.01 Виды интеграции (точка-точка, ESB, API-led)
- Событийная архитектура и async — 03.05.06 Event-Driven Architecture, 03.05.04 Асинхронное взаимодействие (очереди, Kafka, Events)
- Контракты и форматы спецификаций — 03.05.03 Спецификации контрактов (OpenAPI, AsyncAPI, Protobuf), 03.05.02 REST и OpenAPI спецификации, 03.05.04 Контрактное программирование и протоколы (gRPC, GraphQL)
- Моделирование поведения — 03.02.03 Диаграмма последовательности (Sequence Diagram), 03.02.01 Диаграмма прецедентов (Use Case Diagram)
- Данные — 03.03.01 ER-диаграммы (сущность-связь), 03.03.03 Словарь данных (описание)
- HTTP, SOAP, практика API — 07.02 Принципы работы HTTP, REST, SOAP, 07.02 Работа с API (практика), 07.03 Основы XML, JSON, YAML, 07.07 Сетевые основы (подсети, протоколы и маршрутизация)
- NFR, безопасность, rate limiting, версионирование — 08.02 Нефункциональные требования (НФТ) — классификация и стандарты, 03.05.05 Безопасность API, 03.06.03 Rate Limiting — управление пропускной способностью, 03.05.07 Управление версионированием API и жизненным циклом
- Требования, приёмка, ADR, шаблоны — 02.03.03 Спецификация требований (SRS, Use Case, User Story), 02.04.02 Критерии приёмки (Acceptance Criteria), 10.01.13 Шаблон архитектурного решения (ADR), 10.01.04 Шаблон спецификации REST API, 10.01.05 Шаблон спецификации SOAP API
Источники и дополнительные материалы
Книги и диссертации
- Fielding R. Architectural Styles and the Design of Network-based Software Architectures (REST) — https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
Стандарты и спецификации
- RFC 9110 — HTTP Semantics — https://www.rfc-editor.org/rfc/rfc9110
- RFC 7807 — Problem Details for HTTP APIs — https://www.rfc-editor.org/rfc/rfc7807
- OpenAPI Specification — https://spec.openapis.org/oas/latest.html
- Google Cloud API Design Guide — https://cloud.google.com/apis/design
- gRPC Documentation — https://grpc.io/docs/
- gRPC Core Concepts — https://grpc.io/docs/what-is-grpc/core-concepts/
- gRPC Status Codes — https://grpc.io/docs/guides/status-codes/
- google.rpc.Status (Rich Error Model) — https://cloud.google.com/apis/design/errors
- Protocol Buffers Language Guide (proto3) — https://protobuf.dev/programming-guides/proto3/
- GraphQL Specification — https://spec.graphql.org/
- GraphQL — Introduction — https://graphql.org/learn/