Ответ
gRPC использует несколько ключевых механизмов для эффективного управления коммуникацией и жизненным циклом запросов. Все они работают поверх HTTP/2.
-
Потоки (Streams) gRPC расширяет стандартную модель "запрос-ответ" с помощью потоков, позволяя клиенту и серверу обмениваться сообщениями в рамках одного gRPC-вызова. Это основа для всех типов взаимодействия:
- Unary RPC: Классический запрос-ответ (технически, поток из одного сообщения в каждую сторону).
- Server-streaming RPC: Клиент отправляет один запрос, сервер отвечает потоком сообщений.
- Client-streaming RPC: Клиент отправляет поток сообщений, сервер отвечает одним сообщением.
- Bidirectional-streaming RPC: Клиент и сервер асинхронно обмениваются потоками сообщений.
// Пример клиента, читающего серверный поток (Server-side streaming) stream, err := client.SubscribeToNews(ctx, &req) if err != nil { /* ... */ } for { // Recv() блокирует до получения нового сообщения или закрытия потока news, err := stream.Recv() if err == io.EOF { // Поток успешно завершен сервером break } if err != nil { /* обработка ошибки */ } log.Printf("New article: %s", news.GetTitle()) }
-
Контекст (
context.Context
) Это основной механизм для управления жизненным циклом запроса. Контекст используется для:- Дедлайны и таймауты: Клиент может указать, сколько он готов ждать ответа. Если время истекает, gRPC автоматически отменяет запрос на всех уровнях (клиент, сервер, любые промежуточные сервисы).
- Отмена (Cancellation): Запрос может быть отменен явным образом (например, пользователь закрыл страницу). Сигнал об отмене распространяется по всей цепочке вызовов, позволяя серверам прекратить бесполезную работу.
- Передача метаданных: Контекст используется для передачи сквозных данных, таких как токены аутентификации или ID трассировки.
-
Интерцепторы (Interceptors) Это аналог Middleware в веб-фреймворках. Интерцепторы перехватывают входящие и исходящие gRPC-вызовы, позволяя реализовать сквозную логику:
- Unary Interceptors: для одиночных запросов.
- Stream Interceptors: для потоковых вызовов.
Типичные задачи для интерцепторов: логирование, сбор метрик, аутентификация/авторизация, трассировка, управление retry-логикой.
-
HTTP/2 как транспорт Вся коммуникация в gRPC происходит поверх одного TCP-соединения благодаря мультиплексированию в HTTP/2. Это позволяет одновременно выполнять множество запросов и потоков без блокировок и накладных расходов на установку новых соединений, что делает gRPC очень производительным.