gRPC или REST: как выбрать протокол для своих сервисов

Бенчмарк обещал «в десять раз быстрее», а наш замер показал в 1,7–1,8 раза. Что с этим делать при выборе протокола

gRPC или REST: как выбрать протокол для своих сервисов

Ваша команда пилит новый сервис. Самый умный разработчик приносит бенчмарк: «gRPC в десять раз быстрее». Другой резонно спрашивает: и что, теперь надо выкинуть Postman, Swagger и привычный JSON? Так выбор между gRPC и REST быстро превращается в ломание копий.

Спойлер: победителя не будет. REST удобен браузеру и внешним интеграторам, gRPC — частым межсервисным вызовам и потокам. Давайте разберёмся, в чём разница и что выбирать под разные задачи.

ВАМ ПРИШЛО ПРИГЛАШЕНИЕ 💌
Приходите к нам в соцсети поделиться своим мнением и почитать, что пишут другие. А ещё там выходит дополнительный контент, которого нет на сайте — шпаргалки, опросы и разная дурка. В общем, вот тележка, вот ВК — велком!

Что такое gRPC и REST

REST — архитектурный стиль работы с ресурсами через HTTP: например, GET /users/42 получает пользователя. REST API часто передаёт данные в JSON, хотя сам REST не требует именно этот формат.

gRPC — фреймворк удалённых вызовов: клиент вызывает метод удалённого сервиса почти как обычную функцию. Контракт описывают в .proto, из него генерируются клиентские и серверные заготовки, а сообщения обычно передаются в бинарном Protocol Buffers, или protobuf, поверх HTTP/2.

REST задаёт архитектурный подход, а gRPC — RPC-модель с контрактом и кодогенерацией. gRPC создан в Google; на октябрь 2026 года он остаётся проектом CNCF Incubating. Поддерживаются в том числе Go, Java, C++ и Python. Для Rust в 2026 году вышел preview клиента, серверная часть ещё разрабатывается.

Базовую механику REST мы разбирали в материале Как устроены API: разбираемся на примере REST API.

Как работают gRPC и REST

Путь REST-запроса

Для пользователя 42 клиент выбирает метод и URL, добавляет заголовки и отправляет запрос. Сервер отвечает HTTP-статусом и, например, JSON.

Запрос: GET /users/42

 {
   "id": 42,
   "name": "Ada Lovelace",
   "email": "ada@example.com"
 }

JSON — текстовый формат, поэтому ответ видно в DevTools, curl или Postman. Подробнее — в материале JSON: что это за формат и как с ним работать. REST API может работать поверх HTTP/1.1 или HTTP/2, а результат запроса выражается обычным HTTP-кодом: 200, 404, 500 и так далее.

Путь gRPC-вызова

В gRPC сначала описывают сервис в .proto. Для того же GetUser контракт может выглядеть так:

protobuf
 // Указываем синтаксис Protocol Buffers.
 syntax = "proto3";
 // Задаём пространство имён.
 package users.v1;
 // Описываем запрос.
 message GetUserRequest {
   // Передаём идентификатор пользователя.
   int32 id = 1;
 }
 // Описываем ответ.
 message User {
   // Возвращаем идентификатор, имя и почту.
   int32 id = 1;
   string name = 2;
   string email = 3;
 }
 // Объявляем сервис.
 service UserService {
   // Связываем запрос и ответ с методом.
   rpc GetUser(GetUserRequest) returns (User);
 }

Генератор создаёт клиент и серверные заготовки. GetUser() сериализуется protobuf и уходит по HTTP/2 с метаданными. Финальный grpc-status приходит в трейлерах — как чек после покупки: тело ответа закончилось, а итог вызова приходит следом.

Схема 1. Путь REST-запроса и gRPC-вызова
Схема 1. Путь REST-запроса и gRPC-вызова

gRPC против REST

Сравним gRPC и REST по основным параметрам. Один и тот же параметр может быть полезен для внутреннего сервиса и неудобен для публичного API.

ПараметрRESTgRPC
КонтрактОбычно OpenAPI рядом с кодом.proto как исходная схема
ФорматЧасто JSONОбычно protobuf
ТранспортHTTP/1.1 или HTTP/2HTTP/2
СтримингSSE, WebSocket, длинные опросыЧетыре типа RPC
БраузерРаботает напрямуюgRPC-Web, Connect или gateway
Ручная отладкаcurl, Postman, DevToolsgrpcurl, .proto, серверная рефлексия
HTTP-кешGET, Cache-Control, ETagСтандартные RPC идут через POST
Порог входаHTTP и JSON знакомы веб-командамНужны .proto и кодогенерация
Зрелость инструментовHTTP/OpenAPI поддерживают браузеры, прокси и большинство веб-стековОфициальные SDK покрывают основные языки; ручные инструменты обычно требуют схему или рефлексию

В споре gRPC против REST не смешивайте gRPC и protobuf. Protobuf отвечает за схему и сериализацию, gRPC — за вызовы и транспорт. HTTP-кеш переносится не напрямую: стандартные RPC идут через POST и собственные статусы.

Откуда берётся выигрыш в скорости

Производительность gRPC складывается из нескольких деталей. Protobuf передаёт номера полей вместо имён — как если бы вместо названий столбцов пересылали их номера. Бинарное сообщение обычно компактнее JSON и не требует разбора текста.

HTTP/2 умеет мультиплексировать запросы: несколько потоков идут по одному соединению, как по одной широкой трубе. gRPC также переиспользует канал и сжимает заголовки. В руководстве по производительности gRPC прямо рекомендуют переиспользовать стабы и каналы.

Для статьи мы сделали локальный замер одного вызова. Стенд: Linux 6.18.44, 5 vCPU AMD EPYC 9V74, Python 3.13.5; grpcio 1.80.0, protobuf 6.33.6, FastAPI 0.128.2, Uvicorn 0.48.0, httpx 0.28.1. Оба сервиса работали на 127.0.0.1 без TLS: REST — через одно постоянное HTTP-соединение, gRPC — через один канал.

Замерялся не короткий пример выше: User содержал id, name, email, bio на 820 символов, active и score — 867 байт protobuf и 913 байт JSON. После 500 прогревочных запросов шли 10 000 последовательных вызовов одним клиентом, поэтому параллельное мультиплексирование тест не измерял.

В трёх прогонах медиана gRPC была 0,33–0,35 мс, REST — 0,59–0,62 мс; пропускная способность — 2,65–2,93 против 1,59–1,65 тысячи запросов в секунду. Это результат конкретного стека. По медиане вышло примерно в 1,7–1,8 раза, а не в десять.

Выигрыш съедают редкие запросы, прокси, гейтвеи и работа с базой: десятки миллисекунд в БД перекроют экономию на сериализации. При новом соединении добавляется его установка; про TLS — в материале TLS-протокол.

Стриминг в gRPC и REST

В документации это называется gRPC streaming: потоковая передача встроена в модель вызовов. У gRPC четыре типа вызовов:

  • Унарный вызов — один запрос и один ответ, например получение профиля.
  • Серверный поток — один запрос и много ответов: например, выдача длинного списка порциями.
  • Клиентский поток — много сообщений от клиента и один ответ: например, загрузка файла кусками.
  • Двунаправленный поток — обе стороны отправляют сообщения независимо, например обмениваются телеметрией в реальном времени.

REST закрывает те же задачи иначе: Server-Sent Events передаёт поток от сервера, WebSocket даёт двусторонний обмен, длинные опросы — редкие обновления. Файлы можно загружать частями по HTTP.

Это не делает REST непотоковым: если поток — часть контракта, gRPC описывает его в .proto; для одного браузерного канала WebSocket или SSE могут быть проще.

Что происходит с gRPC в браузере

Обычный gRPC неудобно вызывать из браузерного JavaScript из-за трейлеров: финальный статус RPC приходит после тела ответа, а браузерные API не дают приложению читать такие HTTP-трейлеры так, как ожидает gRPC.

Поэтому появился gRPC-Web. Между браузером и сервисом обычно ставят Envoy — прокси, который переводит gRPC-Web в gRPC. Трейлеры он кладёт в тело ответа; у фрейма остаётся пятибайтовый префикс: байт флагов и четыре байта длины. В обычном gRPC финальный статус приходит отдельно — как чек после покупки. Браузер не умеет читать такие HTTP-трейлеры, поэтому gRPC-Web переносит статус внутрь тела ответа.

Схема 1. Путь REST-запроса и gRPC-вызова
Схема 1. Путь REST-запроса и gRPC-вызова

Ошибка RPC может приехать с HTTP 200, поэтому обычный мониторинг увидит успех. В DevTools бинарные данные требуют понимания фреймов. grpc-web поддерживает унарные и серверные потоки, но не клиентский и двунаправленный стриминг. Ограничения разбирает Buf.

Connect сохраняет protobuf-контракт, но для унарных вызовов использует обычные HTTP-коды и работает из браузера без переводящего прокси. Поэтому фронтовый API часто оставляют на REST или Connect, а gRPC — внутри.

Полезный блок со скидкой

По промокоду: KOD (можно просто нажать) — вы получите скидку на все курсы Практикума.

Если хочется проектировать сервисы, которые общаются между собой по gRPC и REST, посмотрите курс Микросервисная архитектура: расширенная версия. Если пока не хватает базы бэкенда, начните с курса Python-разработчик. 

Бесплатные вводные курсы в Практикуме тоже есть — например, Основы работы с базами данных и SQL.

Как отлаживать gRPC и REST

REST проверяют curl, Postman и Swagger, а JSON читается глазами. Подробнее — Что такое Swagger и Как тестируют API.

grpcurl и серверная рефлексия

Для gRPC есть grpcurl. При серверной рефлексии — служебном API со схемой сервиса — достаточно адреса и имени метода. Официальная документация gRPC прямо называет grpcurl и Postman инструментами, которые используют рефлексию для отладки.

 # Вызываем локальный сервер без TLS и передаём аргумент метода.
 grpcurl -plaintext -d '{"id": 42}' localhost:50051 users.v1.UserService/GetUser

Пример ответа:

 {
   "id": 42,
   "name": "Ada Lovelace",
   "email": "ada@example.com"
 }

Без рефлексии grpcurl нужен .proto или descriptor set — скомпилированное описание схемы. Бинарный лог без схемы не прочитаешь, поэтому нужны трассировка и структурированные логи.

Контракт и версионирование API

В REST контракт обычно фиксируют OpenAPI рядом с кодом. В gRPC исходным контрактом становится .proto. Версионирование API нужно обоим: несовместимое изменение может сломать старый клиент.

У protobuf есть строгие правила обратной совместимости. Номер опубликованного поля менять нельзя: он идентифицирует поле на проводе. Удалённый номер помечают reserved. Новое поле старый клиент просто не знает и пропускает.

Правильно:

protobuf
 // Выбираем синтаксис proto3.
 syntax = "proto3";
 // Описываем обновлённое сообщение.
 message User {
   // Остальные опубликованные поля остаются без изменений.
   int32 id = 1;
   string name = 2;
   // Запрещаем повторно использовать удалённый номер email.
   reserved 3;
   // Добавляем новое поле под новым номером.
   string phone = 4;
 }

Если в опубликованной версии email уже имел номер 3, так делать нельзя:

protobuf
 // Выбираем синтаксис proto3.
 syntax = "proto3";
 // Показываем несовместимое изменение.
 message User {
   // Нельзя переносить опубликованное поле на другой номер.
   string email = 7;
 }

REST тоже можно сломать: если строковое поле внезапно стало объектом, старый клиент может не разобрать ответ. Несовместимые изменения обычно выносят в новую версию пути, например /v2/users, или выбирают версию через заголовок.

Когда использовать gRPC, а когда REST

Когда использовать gRPC, решают по потребителю и трафику. Контекст есть в материалах Что такое микросервисы и Микросервисы или монолит: когда что выбирать.

СценарийВыборОбоснование
Частые вызовы между внутренними сервисамиgRPC чащеОдин долгоживущий канал, protobuf и генерируемый контракт
Публичный API для внешних разработчиковREST или REST-gatewayОбычные HTTP-инструменты и OpenAPI снижают порог интеграции
Запросы из браузерного фронтендаREST или ConnectНе нужен перевод gRPC-Web через отдельный прокси
Мобильный клиент на плохой связиgRPC, если обе стороны под вашим контролемКомпактный protobuf полезен; иначе REST проще диагностировать обычными HTTP-инструментами
Подрядчик без опыта protobufREST или gatewayНе нужно внедрять .proto, генераторы и новый цикл сборки у партнёра
Телеметрия потокомgRPC чащеДвунаправленный поток описывается прямо в контракте
Редкие фоновые интеграции и вебхукиREST чащеПреимущества постоянного gRPC-канала почти не используются

Публичный REST API можно поднять по инструкции Создаём API на FastAPI. Для контролируемых клиентов и частых внутренних вызовов естественнее бывает gRPC. Если задержка критична, замеряйте свою полезную нагрузку, сеть, прокси и базу.

Как совмещать gRPC gateway и REST

Частая схема — gRPC внутри и REST наружу. gRPC-Gateway читает .proto и генерирует обратный прокси: он принимает HTTP/JSON и перенаправляет запрос во внутренний gRPC-сервис. Из того же контракта можно получить OpenAPI.

Схема 3. gRPC внутри, REST наружу через gRPC-Gateway
Схема 3. gRPC внутри, REST наружу через gRPC-Gateway

Связка сохраняет типизированный внутренний контракт и привычный внешний API. Цена — лишний сетевой переход, преобразование JSON/protobuf и ещё один компонент. Схема оправдана, когда gRPC нужен внутри, а снаружи требуется обычный HTTP API.

Ошибки при переходе на gRPC

  1. Переезд ради чужого бенчмарка. Сервис может по-прежнему ждать базу, а задержка почти не изменится. Сначала измерьте свой сценарий.
  2. gRPC наружу без учёта клиентов. Внешним потребителям нужны protobuf-инструменты, браузеру — веб-слой. Проверьте аудиторию и при необходимости оставьте gateway.
  3. Перенумерация полей после релиза. Так ломается совместимость бинарных сообщений. Номера не переиспользуют, удалённые помечают reserved.
  4. Вызовы без дедлайна. Дедлайн вызова — крайний срок, после которого RPC отменяется. Без него зависший клиент может держать вызов дольше, чем нужно.
  5. Расчёт на HTTP-кеш. CDN не кеширует обычный gRPC-вызов как GET. Если кеширование — часть API, нужен отдельный кеш приложения или HTTP-граница.

Частые вопросы

Заменит ли gRPC REST полностью?

Нет. gRPC удобен для типизированных RPC и потоков между контролируемыми клиентами, REST — для браузеров, публичных API и стандартных HTTP-инструментов.

Работает ли gRPC поверх HTTP/3?

Поддержка зависит от стека. Базовый gRPC ориентирован на HTTP/2. В разборе gRPC поверх HTTP/3 трейлеры были одним из блокеров; в quic-go их добавили в версии 0.47.0. Но поддержка всё ещё различается между библиотеками, поэтому проверяйте конкретные клиент и сервер.

Нужен ли protobuf, если нравится JSON?

Protobuf — стандартный формат gRPC, хотя сама модель допускает другие сериализаторы. Если важны человекочитаемый JSON и обычные веб-инструменты, REST или Connect могут быть проще.

Можно ли отдавать gRPC прямо в мобильное приложение?

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

Что выбрать для пет-проекта?

Для небольшого CRUD API с браузером REST обычно требует меньше инфраструктуры. Если цель проекта — изучить protobuf, кодогенерацию и потоковые RPC, gRPC даст больше материала.

Что выбрать в итоге

Сведите выбор к двум вопросам: кто потребляет API и насколько часто идут запросы. Для браузера и внешних интеграций важнее совместимость с обычным HTTP; для частых внутренних вызовов и потоков — строгий контракт и особенности gRPC.

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

Советуем дальше почитать

Клиент-серверная архитектура — что это, каковы принципы работы и примеры — модель «клиент — сервер», сравнение с P2P и serverless, плюсы и минусы. Основа, на которой строятся оба протокола из статьи.

Как тестируют бэкенд — направления тестирования бэкенда: API, нагрузочное, базы данных и инструменты вроде Swagger, Postman и JMeter. Продолжает тему отладки и замеров.

Роадмап Golang 2026: пошаговый план с нуля до первого оффера — путь через основы Go, конкурентность, бэкенд и тестирование. Для тех, кто решил попробовать gRPC на Go.

Что такое Site Reliability Engineering — что такое SRE, SLI, SLO, SLA и мониторинг. Про то, как следить за сервисами после того, как протокол выбран.

7 книг для бэкенд-разработчика про алгоритмы, SQL и архитектуру — книги про микросервисы, работу с данными и надёжность систем. Для тех, кто хочет разобраться в теме глубже одной статьи.

Бонус для читателей

Если вам интересно погрузиться в мир IT и при этом немного сэкономить, держите наш промокод на курсы Практикума. Он даст вам скидку при оплате, поможет с льготной ипотекой или безлимитом на маркетплейсах. Ладно, окей, это просто скидка, без остального, но хорошая.

Вам может быть интересно
medium