REST vs gRPC: protobuf и когда RPC

О лекции

REST в быту — ресурсы, JSON и семантика HTTP. gRPC — контракт в .proto, protobuf на проводе и вызовы как функции, обычно поверх HTTP/2. Публичному браузерному API чаще нужен REST; внутреннему mesh — RPC.

API и RPC http собеседование

REST в быту — не строгий HATEOAS. Обычно имеют в виду: URL как ресурсы, глаголы, коды статуса, идемпотентность GET/PUT/DELETE, кэш GET, версионирование. Тело — JSON. Это универсальный край: браузер, мобилка, CDN, curl, вебхуки.

gRPC описывает сервис в файле .proto. Оттуда генерируют клиент и сервер. На проводе — protobuf, не JSON. Унарный вызов выглядит как функция. Есть server, client и двунаправленный streaming. Дедлайны и статусы — часть модели, не «ещё один заголовок руками».

Это разные контракты, не «gRPC — быстрый REST». Компактность и схема помогают между сервисами. Браузер сам по себе не говорит gRPC: нужен grpc-web или JSON-прокси.

Пример. Публично: POST /charges с JSON, CDN, curl с ноутбука партнёра. Внутри кластера: Billing.Charge по gRPC между billing и payments. Два контракта сразу без причины удваивают версионирование.

Protobuf и совместимость

Поле в protobuf — номер, не имя JSON-тега в Go. Добавить optional-поле с новым номером — обычно совместимо. Переименовать поле в исходнике, не трогая номер, для бинарного протокола безопасно.

Переиспользовать номер поля под другой тип — ломающее изменение. Старые клиенты прочитают мусор. Комментарий в .proto ни на что не влияет.

syntax = "proto3";
service Billing {
  rpc Charge(ChargeReq) returns (ChargeResp);
}
message ChargeReq {
  string idempotency_key = 1;
  int64 amount_cents = 2;
  // reserved 3; не отдавать номер «на будущее» в новый тип
}
// плохо: field 2 = string после того, как клиенты слали int64
// JSON/REST публично:
//   POST /charges  + Idempotency-Key + CDN/кэш на GET

Контракт gRPC — .proto и номера полей. Ломает совместимость переиспользование номера, не новое optional-поле.

Когда что

Публичное API, партнёры, мобилки через CDN, кэш GET, вебхуки — чаще REST/JSON. Экосистема HTTP уже есть. Внутренний mesh, низкая латентность, стриминг, много сервисов на одной схеме — gRPC уместен.

Нагрузка gRPC балансируется на L7, который понимает HTTP/2. Обычный HTTP/1 прокси ломает gRPC.

  • Плюсы gRPC: компактнее типичного JSON, строгая схема, стримы, дедлайны из коробки.
  • Минусы: отладка сложнее curl, браузеру нужен мост, ломающие номера полей больнее «ещё одно JSON-поле».
  • REST сильнее там, где кэш, семантика методов и человекочитаемый край.
Типичная ошибка

Сказать «protobuf самодокументируется» без политики номеров полей. Или «REST всегда медленнее» — на публичном API выигрыш съест сеть, а операционка двух стеков останется.

На собеседовании

Сравните контракт: JSON+HTTP-семантика против .proto и protobuf. Для браузера и CDN — REST; gRPC в браузере нужен мост. Ломающее изменение — переиспользовать номер поля, не добавить новое.