
В статье сравним REST, gRPC и GraphQL с точки зрения производительности, гибкости и архитектуры микросервисов. Покажем, как объединить GraphQL и gRPC для фронтенда и бэкенда, чтобы получить мощный API без лишнего трафика и задержек.
gRPC — это современный высокопроизводительный фреймворк для удалённого вызова процедур (RPC), разработанный Google. В отличие от REST, основанного на HTTP и текстовых форматах (например, JSON), gRPC использует HTTP/2 и бинарный протокол Protocol Buffers (protobuf), с тегами полей и типами данных. Хранит только значения и короткие бинарные метки, что экономит трафик до 10 раз по сравнению с JSON и XML. Это делает gRPC более быстрым, эффективным и удобным для межсервисного взаимодействия.
Ключевые особенности gRPC:
Бинарный протокол (protobuf) – компактный и быстрый.
HTTP/2 - мультиплексирование, потоковая передача, уменьшение задержки.
-
Поддержка нескольких режимов взаимодействия:
a. Унарные RPC (аналог REST: запрос → ответ).
b. Стриминг от сервера (сервер отправляет несколько ответов).
c. Стриминг от клиента (клиент отправляет несколько запросов).
d. Двунаправленный стриминг (обмен сообщениями в реальном времени).
Генерация кода из .proto файлов - автоматическая генерация клиентских и серверных stubs.
Поддержка множества языков (C++, Java, Python, Go, Rust, C#, JavaScript и др.).
Сравнение gRPC и REST:
Характеристика |
gRPC |
REST (обычно JSON/HTTP) |
Протокол |
HTTP/2 + Protobuf (бинарный) |
HTTP/1.1/2 + JSON/XML (текст) |
Скорость |
Высокая (меньше оверхеда) |
Медленнее (текстовый парсинг) |
Стриминг |
Поддерживается |
Только через WebSockets/Long Polling |
Генерация кода |
Да (через .proto) |
Нет (Swagger/OpenAPI — опционально) |
Кэширование |
Сложнее |
Легко (на основе HTTP) |
Поддержка браузеров |
Ограничена (нужен gRPC-Web) |
Полная |
Когда выбирать gRPC?
Микросервисы (быстрое взаимодействие между сервисами).
Данные реального времени (стриминг, чаты, игры).
Системы с высокими нагрузками (меньше трафика, быстрее сериализация).
Когда REST лучше?
Публичные API (легче документировать через OpenAPI).
Браузерные клиенты (gRPC требует gRPC-Web).
Простота (если не нужна высокая производительность).
Вывод
gRPC — это не просто "аналог REST", а более мощный и эффективный протокол для сервисного взаимодействия, но со своими плюсами и минусами. Выбор зависит от задачи.
При использовании gRPC часто применяется гибридная архитектура:
Клиент ↔ Backend (REST/HTTP) – для взаимодействия с браузерами/мобильными приложениями.
Backend ↔ Микросервисы (gRPC) – для быстрого обмена данными внутри системы.
Почему это хорошо:
Гибкость для клиентов: REST/HTTP проще для фронтенда (браузеры, мобильные приложения); JSON удобнее отлаживать (через DevTools, Postman, curl).
Производительность для микросервисов: gRPC даёт высокую скорость и низкие задержки и экономит ресурсы за счёт бинарного protobuf и HTTP/2.
Лёгкость масштабирования: микросервисы на gRPC можно масштабировать без потери скорости.
Как это реализуется на практике:
-
Клиентский API (REST)
– Принимает запросы в JSON (например, /api/users).
– FastAPI (Python), Express (Node.js), Spring Boot (Java) и т. д.
-
Внутренний gRPC
– REST-бэкенд преобразует JSON в protobuf и вызывает микросервисы.
– Микросервисы общаются друг с другом по gRPC.
Пример потока данных:
[Браузер] → HTTP/JSON → [REST API Gateway] → gRPC/protobuf → [UserService]
→ [OrderService]
→ [PaymentService]
Альтернативы:
GraphQL вместо REST – если клиенту нужна гибкость в запросах.
gRPC-Web – если хочется сразу gRPC в браузере (но требует прокси).
gRPC-Web имеет ограничения по сравнению с обычным gRPC, и подходит не для всех сценариев.
Главные ограничения gRPC-Web:
-
Не поддерживает все типы gRPC-стриминга
Работает: Унарные RPC (запрос → ответ).
Работает: Серверный стриминг (ответы в потоке).
Не работает: Клиентский и двунаправленный стриминг (как в нативном gRPC).
-
Требует прокси (например, Envoy)
– Браузеры не поддерживают HTTP/2 в чистом виде для gRPC, поэтому нужен адаптер (gRPC-Web → HTTP/1.1 или HTTP/2).
-
Меньшая производительность, чем у нативного gRPC
– Из-за проксирования и адаптации под HTTP/1.1 могут быть небольшие накладные расходы.
-
Ограниченная поддержка некоторых языков
– gRPC-Web клиенты есть для JS/TypeScript, но поддержка в других языках (например, для мобильных приложений) слабее.
Вывод:
gRPC-Web — хорош для унарных вызовов и серверного стриминга в браузере, но не заменяет нативный gRPC или WebSockets для сложных сценариев. Если ваш фронтенд работает с микросервисами через REST-шлюз, а внутри всё на gRPC — это хорошее решение.
GraphQL можно использовать в качестве альтернативы REST для шлюза между фронтендом и бекендом.
GraphQL vs REST как замена для gRPC-шлюза:
Критерий |
REST (лучше для) |
GraphQL (лучше для) |
Гибкость запросов |
Жёсткие эндпоинты |
Клиент сам выбирает поля ( |
Передача данных |
Часто over/under-fetching* |
Только нужные данные |
Сложность API |
Проще для простых сценариев |
Требует изучения GraphQL |
Кэширование |
HTTP-кэширование (ETag, Last-Modified) |
Сложнее (клиентское кэширование через Apollo) |
Скорость разработки |
Быстро для CRUD |
Нужна настройка резолверов и схем |
Интеграция с gRPC |
Просто (REST → gRPC) |
Можно (GraphQL → gRPC через резолверы) |
* over-fetching - это ситуация, когда клиент получает больше данных, чем ему нужно
* в REST можно бороться с over-fetching через запрос с параметрами. Пример: GET /api/users/123?fields=name,email . Но это не всегда предусматривают на практике.
Когда GraphQL лучше REST?
-
Фронтенд требует гибкости
Клиент (например, мобильное приложение) хочет запрашивать только нужные поля, избегая over-fetching.
Например:
query {user(id: "123") {namelastLogin}}В REST пришлось бы либо отдавать весь объект, либо делать отдельный эндпоинт.
-
Агрегация данных из нескольких микросервисов:
GraphQL-шлюз может объединять данные из разных gRPC-сервисов в один запрос.
-
Часто меняющиеся требования к API:
Не нужно создавать новые эндпоинты — просто меняем запрос на клиенте.
Когда REST предпочтительнее?
-
Простой CRUD-бэкенд:
Если фронтенд всегда получает одни и те же данные (например, /api/users), GraphQL — избыточен.
-
Кэширование на уровне HTTP:
REST с ETag и Cache-Control кэшируется лучше, чем GraphQL.
-
Минимальная сложность:
GraphQL требует настройки схем, резолверов, Apollo Client (для фронтенда).
Вывод: что выбрать?
GraphQL – если фронтенду нужна гибкость, агрегация данных или вы работаете с часто меняющимся API.
REST – если API простые, важна простота разработки и HTTP-кэширование.
Немного про over-fetching
Over-Fetching (избыточная выборка) — это ситуация, когда клиент получает больше данных, чем ему нужно.
Пример в REST
Допустим, есть эндпоинт: GET /api/users/123
Он возвращает все поля пользователя:
{
"id": "123",
"name": "Alice",
"email": "alice@example.com",
"age": 30,
"address": "123 Main St",
"phone": "+123456789",
"registrationDate": "2023-01-01"
}
Но клиенту (например, фронтенду) нужно только name и email. Всё остальное — лишняя нагрузка на сеть и парсинг.
Как GraphQL решает проблему over-fetching?
В GraphQL клиент явно указывает, какие поля ему нужны:
query {
user(id: "123") {
name
email
}
}
Сервер вернёт только запрошенные данные:
{
"user": {
"name": "Alice",
"email": "alice@example.com"
}
}
Нет лишних данных → меньше трафика и быстрее загрузка.
Ещё примеры over-fetching:
Мобильное приложение: на слабом интернете загружает ненужные 20 полей вместо 3.
Дашборды: запрашивают всю сущность, хотя нужна только статистика.
Противоположность over-fetching — under-fetching
Это когда данных не хватает, и клиенту приходится делать дополнительные запросы.
Пример в REST:
GET /api/users/123→ Основная информация
GET /api/users/123/orders → Отдельный запрос для заказов
В GraphQL можно получить всё за один запрос:
query {
user(id: "123") {
name
orders {
id
total
}
}
}
Когда over-fetching не страшен?
Если данные кешируются (например, CDN).
Если клиенту всё равно нужны все поля (например, админка).
gRPC + GraphQL в одной архитектуре
Это частый сценарий:
На фронте — GraphQL (гибкий, понятный, удобно для UI).
Внутри — gRPC (быстро, надёжно, чётко).
Схема:
[Браузер] → GraphQL → [API Gateway] → gRPC → [UserService | OrderService | PaymentService]
GraphQL работает как "умный фасад" �� запрашивает нужные поля у микросервисов и возвращает клиенту уже агрегированный результат. Чтобы данные ходили в gRPC также гибко, как и в GraphQL, можно использовать механизм FieldMask из Protocol Buffers. Он позволяет передавать в запросе список нужных полей, чтобы сервис возвращал только их, без лишних данных. На стороне БД это можно реализовать через jOOQ или Criteria API.
Пример запроса:
query {
user(id: "123") {
name
orders {
id
total
}
}
}
API Gateway на GraphQL обращается к нескольким gRPC-сервисам, получает ответы и собирает их в итоговый JSON. Это снижает объём трафика и ускоряет сериализацию ответов.
Пример кода: GitHub
cmyser
У графа куча проблем
Есть решение поинтереснее
https://habr.com/ru/articles/680376/ HARP human api rest protocol