Транспорт бэкенда

gRPC: высокопроизводительный RPC

В 2015 году Google обрабатывал 10 миллиардов RPC-вызовов в секунду между внутренними сервисами. REST с JSON физически не справлялся с такой нагрузкой. Решение - gRPC с Protocol Buffers. Сегодня это стандарт де-факто для межсервисного взаимодействия в крупных системах: Kubernetes API, Netflix, Dropbox, CoreOS etcd - все используют gRPC.

  • **Kubernetes API Server** - весь внутренний протокол kubelet с control plane работает на gRPC
  • **Netflix** - gRPC для коммуникации между сотнями микросервисов стриминговой платформы
  • **Dropbox** - перешли с REST на gRPC, получили 70% снижение нагрузки на сеть

Protocol Buffers IDL

В 2015 году Google открыл исходный код своего внутреннего RPC-фреймворка, который к тому времени уже обрабатывал миллиарды запросов в секунду между сервисами поиска, Gmail и YouTube. Секрет его скорости - **Protocol Buffers**: бинарный формат сериализации, который в 3-10 раз компактнее JSON и декодируется в 10-100 раз быстрее.

Центральная идея gRPC - **IDL (Interface Definition Language)**. Сначала описывается контракт в `.proto` файле, затем из него генерируется код для любого из 11 поддерживаемых языков. Сервис и клиент гарантированно говорят на одном языке - несоответствие типов становится ошибкой компиляции, а не runtime-сюрпризом.

**Генерация кода:** `protoc --js_out=. --grpc-web_out=. user.proto` - одна команда генерирует клиент и серверные stub-ы. Поменял `.proto` - перегенерировал - ошибки компиляции укажут на несовместимость.

Зачем в Protobuf у каждого поля есть числовой номер (field number)?

Unary и Streaming вызовы

REST знает один режим: запрос - ответ. gRPC работает поверх HTTP/2 и предлагает четыре режима коммуникации. Это не надстройка - это фундаментальная разница в том, как данные передаются по сети.

РежимЗапросОтветПрименение
Unary1 сообщение1 сообщениеCRUD, аутентификация
Server streaming1 сообщениепоток сообщенийэкспорт, прогресс задачи
Client streamingпоток сообщений1 сообщениезагрузка файла по чанкам
Bidirectionalпотокпотокчат, телеметрия, игры

**HTTP/2 под капотом:** каждый gRPC-вызов - это HTTP/2 stream. Несколько одновременных вызовов мультиплексируются по одному TCP-соединению. Никаких head-of-line блокировок как в HTTP/1.1, никакого connection pool overhead.

Сервис генерирует отчёт и хочет показывать прогресс клиенту в реальном времени. Какой режим gRPC подойдёт?

Interceptors и Metadata

gRPC-вызов несёт не только полезную нагрузку - вместе с ним путешествуют **metadata**: пары ключ-значение, которые идут до основного сообщения. Это аналог HTTP-заголовков: токены авторизации, trace-id, версия клиента.

**Interceptors** - это middleware gRPC. Они перехватывают вызов до и после его обработки, и именно там живёт вся cross-cutting логика: аутентификация, логирование, метрики, retry-политика. Два типа: клиентские (оборачивают исходящий вызов) и серверные (оборачивают обработчик).

**Initial vs Trailing metadata:** Initial metadata отправляется сразу при открытии stream (до данных). Trailing metadata - после последнего сообщения. Например, сервер может передать общее количество записей в trailing metadata после стриминга результатов.

Нужно добавить метрику времени выполнения ко всем gRPC-методам сервиса. Лучший способ:

Deadlines и Cancellation

Представьте: сервис A вызывает B, B вызывает C, C завис на 30 секунд. Без deadline-ов цепочка держит connections и threads на всём пути. Несколько таких зависших цепочек - и ресурсы заканчиваются у всех участников. Это называется **cascading failure** - одна медленная зависимость кладёт весь кластер.

gRPC решает это на уровне протокола: **deadline** - это абсолютное время истечения, которое передаётся по всей цепочке вызовов. Если клиент дал 500ms, сервис B знает, что у него максимум 500ms на весь ответ, включая вызов C. Когда время истекает, gRPC автоматически отменяет вызов через **context cancellation**.

**Deadline vs Timeout:** timeout - это относительное время ("жди 500ms"), deadline - абсолютная метка времени ("до 14:32:00.500"). gRPC использует deadline потому что его можно передавать между сервисами: каждый участник видит сколько реально осталось, а не сколько было изначально.

Почему gRPC использует deadline (абсолютное время), а не timeout (относительное)?

gRPC-Web: браузерное ограничение

Браузеры не умеют gRPC напрямую. Проблема техническая: браузерный Fetch API не даёт управлять HTTP/2 frame-ами так, как это нужно gRPC. Protobuf-кодирование возможно, HTTP/2 multiplexing - нет. Особенно это касается client streaming и bidirectional streaming: браузер не контролирует закрытие stream на нужном уровне.

**gRPC-Web** - это специфичный subset протокола, который работает через стандартный HTTP/1.1 или HTTP/2 с проксированием. Envoy proxy (или grpc-web-proxy) стоит перед gRPC-сервером и транслирует gRPC-Web запросы в обычный gRPC.

**Альтернативы:** Connect Protocol (от Buf) - более современный подход, совместим с gRPC но работает в браузере без proxy. gRPC-Gateway - генерирует REST proxy из .proto аннотаций, полезен когда нужен REST-интерфейс для мобильных клиентов.

gRPC-Web - это полноценный gRPC в браузере

gRPC-Web - ограниченный subset: только Unary и Server streaming. Client streaming и bidirectional недоступны из-за браузерных ограничений Fetch API

Браузер не предоставляет API для управления HTTP/2 stream на нужном уровне абстракции

Почему браузер не может использовать обычный gRPC (без gRPC-Web)?

gRPC: ключевые идеи

  • Protobuf IDL - контракт первичен, код генерируется: несоответствие типов = ошибка компиляции
  • 4 режима: Unary, Server streaming, Client streaming, Bidirectional - всё поверх HTTP/2 multiplexing
  • Interceptors - middleware для auth, tracing, metrics; Metadata - аналог HTTP-заголовков
  • Deadlines передаются по цепочке сервисов - защита от cascading failures
  • gRPC-Web нужен для браузеров: Envoy proxy + только Unary и Server streaming

Связанные темы

gRPC строится на HTTP/2 и дополняет экосистему синхронных протоколов.

  • HTTP/2 и HTTP/3 — HTTP/2 - транспорт gRPC: multiplexing, server push, header compression
  • WebSocket — Альтернатива для real-time: gRPC streaming vs WebSocket
  • Очереди сообщений — Когда нужен async вместо sync RPC

Вопросы для размышления

  • В каких ситуациях gRPC streaming предпочтительнее WebSocket, а в каких - наоборот?
  • Как правильно выбрать deadline для RPC-вызова в production? Какие данные нужны для этого решения?
  • Что происходит с backward compatibility при изменении .proto-схемы в уже работающем сервисе?

Связанные уроки

  • net-24-http2-http3
gRPC: высокопроизводительный RPC

0

1

Войти