Когда один сервис зовёт другой сотни раз в секунду, накладные расходы REST начинают мешать: текстовый JSON надо сериализовать и парсить, заголовки повторяются, а контракт держится «на честном слове» — на документации, которая устаревает. gRPC решает именно эту задачу: строгий контракт, компактный бинарный формат и быстрый транспорт. Разберёмся, как он устроен и когда его стоит брать.
Что такое gRPC
gRPC — это способ вызывать метод чужого сервиса так, будто он локальный: вы пишете orders.Get(id), а под капотом уходит сетевой запрос. Такой подход называется RPC (remote procedure call, удалённый вызов процедуры). Google сделал gRPC поверх двух вещей:
- protobuf (Protocol Buffers) — язык описания контракта и компактный бинарный формат данных;
- HTTP/2 — транспорт с мультиплексированием и постоянными соединениями (разобран в статье про версии HTTP).
В отличие от REST, где вы думаете в терминах ресурсов и URL, в gRPC вы думаете в терминах сервисов и их методов.
Контракт в protobuf
Всё начинается с .proto-файла — это единый источник правды о контракте. В нём описаны сообщения (структуры данных) и сервис с методами:
syntax = "proto3";
message GetOrderRequest {
string id = 1;
}
message Order {
string id = 1;
string status = 2;
int64 amount = 3; // в минимальных единицах, например копейках
}
service OrderService {
rpc GetOrder(GetOrderRequest) returns (Order);
}
Числа = 1, = 2 — это не значения, а номера полей: именно они пишутся в бинарный формат вместо имён. Поэтому protobuf компактнее JSON (нет повторяющихся имён полей) и совместим при эволюции: добавить новое поле с новым номером можно, не сломав старых клиентов.
Кодогенерация: контракт превращается в код
Из .proto инструмент генерирует классы и заглушки на нужном языке — сервер реализует интерфейс, клиент получает готовый вызов. Правило простое: .proto — источник правды, код из него генерируется, а не пишется руками. Это и есть главное отличие от REST: контракт проверяется компилятором. Опечатку в имени поля вы поймаете при сборке, а не в проде.
Четыре вида вызовов
gRPC умеет не только «запрос-ответ». Всего есть четыре режима — за счёт стриминга HTTP/2:
- Унарный — один запрос, один ответ. Как обычный вызов метода.
- Серверный стриминг — один запрос, поток ответов. Например, «подпишись на обновления заказа».
- Клиентский стриминг — поток запросов, один ответ. Например, загрузка данных частями.
- Двунаправленный стриминг — оба конца шлют потоки одновременно. Например, чат или телеметрия.
Стриминг — то, что в REST приходится изобретать (long-polling, WebSocket, SSE), а в gRPC встроено.
Где это применяется
gRPC силён во внутренней связи между сервисами, где обе стороны ваши и важны скорость и строгий контракт:
- Микросервисы, которые часто зовут друг друга: бинарный формат и переиспользуемые HTTP/2-соединения экономят время (о стоимости установки соединений — в статье про соединения и пулы).
- Строго типизированные контракты между командами:
.proto— общий язык, кодогенерация не даёт разойтись. - Потоковые сценарии: телеметрия, подписки, обмен событиями.
Где gRPC — плохой выбор:
- Публичное API для браузеров и сторонних разработчиков. Браузер не умеет gRPC напрямую (нужен прокси grpc-web), а внешним потребителям привычнее REST + JSON, который видно глазами и легко потрогать curl'ом.
- Отладка «на коленке». Бинарный формат не прочитать в логах без инструментов; REST-ответ читается сразу.
- Кэширование HTTP. REST-
GETкэшируется прокси и CDN из коробки; gRPC-вызов — нет.
Где спотыкаются начинающие:
- Тащат gRPC в публичное API ради «скорости», получая мучения с браузерами и внешними клиентами. Для публичного контура REST почти всегда правильнее.
- Меняют номера полей в
.proto— это ломает совместимость. Номер поля неприкосновенен; поле можно только добавить с новым номером или пометить устаревшим. - Забывают про дедлайны и ретраи. Быстрый вызов не значит надёжный — сеть всё так же ненадёжна (см. таймауты и ретраи).
- Ставят gRPC везде «потому что модно», хотя внутри всего пара вызовов в секунду — тогда выигрыш незаметен, а сложность добавилась.
Что учить дальше
gRPC — это одна развилка в проектировании контракта. Рядом — GraphQL, который решает другую боль (гибкие срезы данных для клиента), и базовый REST, от которого стоит отталкиваться по умолчанию. Транспортная основа gRPC — HTTP/2, а надёжность вызовов между сервисами — в статье про таймауты, ретраи и идемпотентность. Как выбор стиля вписывается в проектирование системы целиком — в разделе системного дизайна.