Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → gRPC streaming: паттерны и практика

gRPC streaming на практике: четыре типа потоковой передачи

Как работает gRPC streaming: server/client/bidirectional streaming, backpressure через HTTP/2 flow control и практические паттерны для потоковых RPC.

Прямой ответ

gRPC streaming — потоковая передача данных через gRPC (gRPC — «не один запрос-ответ, а поток» — gRPC — «streaming RPC» — gRPC), четыре типа (gRPC — «четыре типа streaming» — gRPC); 1. Unary RPC (gRPC — «один запрос — один ответ» — gRPC — «обычный RPC» — gRPC — не streaming — gRPC — rpc GetUser(UserRequest) returns (UserResponse) (gRPC — «unary» — gRPC); 2. Server streaming (gRPC — «один запрос — поток ответов» — gRPC — «server streaming» — gRPC — rpc ListUsers(ListRequest) returns (stream UserResponse) (gRPC — «stream в ответе» — gRPC — когда: большие списки (gRPC — «1000 юзеров — stream» — gRPC — «не грузить всё сразу» — ёмкость), прогресс (gRPC — «прогресс операции» — gRPC — realtime); 3. Client streaming (gRPC — «поток запросов — один ответ» — gRPC — «client streaming» — gRPC — rpc UploadFiles(stream FileChunk) returns (UploadResponse) (gRPC — «stream в запросе» — gRPC — когда: загрузка файлов (gRPC — «файл чанками» — gRPC — «не грузить весь файл» — ёмкость), батчи (gRPC — «батч запросов» — gRPC — ёмкость); 4. Bidirectional streaming (gRPC — «поток запросов — поток ответов» — gRPC — «bidirectional streaming» — gRPC — rpc Chat(stream ChatMessage) returns (stream ChatMessage) (gRPC — «stream в обоих» — gRPC — когда: чат (gRPC — «чат — bidirectional» — gRPC — realtime), realtime (gRPC — «realtime — bidirectional» — gRPC — realtime); backpressure (backpressure — HTTP/2 flow control (backpressure — «HTTP/2 — backpressure из коробки» — backpressure — «поток превышает обработку — backpressure» — backpressure — gRPC); когда streaming: большие данные (gRPC — «1000 объектов — stream» — gRPC — «не грузить всё» — ёмкость), realtime (gRPC — «realtime — streaming» — gRPC — realtime), прогресс (gRPC — «прогресс операции» — gRPC — realtime); когда НЕ streaming: простые случаи (gRPC — «unary достаточно» — gRPC — «streaming оверхед» — техдолг), маленькие данные (gRPC — «10 объектов — unary» — gRPC — «streaming не нужен» — техдолг); антипаттерны: streaming для маленьких данных (gRPC — «streaming для 10 объектов» — gRPC — «unary проще» — техдолг), streaming без backpressure (backpressure — «streaming без backpressure» — backpressure — «поток превысил обработку» — backpressure — HTTP/2 flow control — backpressure), streaming без timeout (gRPC — «streaming без timeout» — gRPC — «поток завис» — gRPC — timeout обязателен — gRPC).

Практика: streaming в gRPC Python

Server streaming (gRPC: def ListUsers(self, request, context): for user in db.list_users(): yield user_pb2.UserResponse(id=user.id, name=user.name) (gRPC — «server streaming» — gRPC — yield (gRPC — «yield — поток» — gRPC); Client streaming (gRPC: def UploadFiles(self, request_iterator, context): for chunk in request_iterator: save_chunk(chunk) return UploadResponse(status="ok") (gRPC — «client streaming» — gRPC — request_iterator (gRPC — «iterator — поток» — gRPC); Bidirectional streaming (gRPC: def Chat(self, request_iterator, context): for message in request_iterator: response = process_message(message) yield response (gRPC — «bidirectional streaming» — gRPC — request_iterator + yield (gRPC — «поток в обоих» — gRPC); Timeout (gRPC: context.set_timeout(30) (gRPC — «timeout 30 с» — gRPC — «поток завис — timeout» — gRPC); Backpressure (backpressure — HTTP/2 flow control (backpressure — «HTTP/2 — backpressure» — backpressure — «поток превысил — backpressure» — backpressure — автоматически — backpressure); Мониторинг (метрики: «streaming RPC count», «stream duration» — метрики — алерты — алерты — «streaming завис» — incident).

Практический сценарий: загрузка файла через client streaming

Контекст: сервис загрузки файлов (gRPC), боль: большие файлы (ёмкость — «файл 1 ГБ — unary не подходит» — ёмкость — «unary — весь файл в памяти» — ёмкость); решение — client streaming: (1) схема (gRPC — rpc UploadFile(stream FileChunk) returns (UploadResponse) (gRPC — «client streaming» — gRPC — Protobuf); (2) клиент (gRPC — def file_chunks(): with open("file.bin", "rb") as f: while chunk := f.read(1024*1024): yield FileChunk(data=chunk) (gRPC — «чанки по 1 МБ» — gRPC — ёмкость); (3) сервер (gRPC — def UploadFile(self, request_iterator, context): for chunk in request_iterator: save_chunk(chunk) return UploadResponse(status="ok") (gRPC — «client streaming» — gRPC); (4) backpressure (backpressure — HTTP/2 flow control (backpressure — «сервер не успевает — backpressure» — backpressure — автоматически — backpressure); (5) timeout (gRPC — context.set_timeout(300) (gRPC — «timeout 5 мин» — gRPC — «файл большой — timeout больше» — gRPC); (6) мониторинг (метрики — «upload duration», «chunk count» — метрики — алерты — алерты); результат: файл 1 ГБ — чанки по 1 МБ (ёмкость — «не весь файл в памяти» — ёмкость — backpressure (backpressure — «сервер не успевает — backpressure» — backpressure — timeout (gRPC — «5 мин — timeout» — gRPC); вывод: client streaming решили задачу (большие файлы — ёмкость — ADR — «unary для больших файлов» — антипаттерн — техдолг).

FAQ

Чем gRPC streaming отличается от unary RPC? Unary RPC (gRPC — «один запрос — один ответ» — gRPC — «обычный RPC» — gRPC — rpc GetUser(UserRequest) returns (UserResponse) (gRPC — «unary» — gRPC); Streaming (gRPC — «поток» — gRPC — «не один, а поток» — gRPC — server/client/bidirectional (gRPC — «три типа streaming» — gRPC); когда unary: простые случаи (gRPC — «unary достаточно» — gRPC — маленькие данные (gRPC — «10 объектов — unary» — gRPC), когда streaming: большие данные (gRPC — «1000 объектов — stream» — gRPC — realtime (gRPC — «realtime — streaming» — gRPC — realtime); «streaming для маленьких» — антипаттерн (unary проще — gRPC — ADR — техдолг).

Какие четыре типа gRPC streaming бывают?

  1. Unary (gRPC — «один запрос — один ответ» — gRPC — не streaming — gRPC), 2. Server streaming (gRPC — «один запрос — поток ответов» — gRPC — «server streaming» — gRPC — большие списки (gRPC — «1000 юзеров» — gRPC), 3. Client streaming (gRPC — «поток запросов — один ответ» — gRPC — «client streaming» — gRPC — загрузка файлов (gRPC — «файл чанками» — gRPC), 4. Bidirectional streaming (gRPC — «поток запросов — поток ответов» — gRPC — «bidirectional» — gRPC — чат (gRPC — «чат — bidirectional» — gRPC — realtime); «четыре типа» — unary + три streaming (gRPC — «unary + server/client/bidirectional» — gRPC — ADR — техдолг).

Как работает backpressure в gRPC streaming? Backpressure (backpressure — HTTP/2 flow control (backpressure — «HTTP/2 — backpressure из коробки» — backpressure — «поток превысил обработку — backpressure» — backpressure — автоматически (backpressure — «gRPC — backpressure автоматически» — backpressure — gRPC); HTTP/2 flow control (backpressure — «HTTP/2 — flow control» — backpressure — «получатель не готов — отправитель ждёт» — backpressure — backpressure); «streaming без backpressure» — нет (HTTP/2 — backpressure из коробки — backpressure — ADR — техдолг).

Как обрабатывать ошибки в gRPC streaming? Ошибки (gRPC — context.abort(grpc.StatusCode.INVALID_ARGUMENT, "Invalid data") (gRPC — «ошибка — abort» — gRPC — «streaming прерван» — gRPC); Timeout (gRPC — context.set_timeout(30) (gRPC — «timeout 30 с» — gRPC — «поток завис — timeout» — gRPC); Retry (retry — клиент ретраит (retry — «streaming упал — retry» — retry — gRPC); «streaming без timeout» — антипаттерн (поток завис — gRPC — timeout обязателен — gRPC — ADR — техдолг).

Источники: gRPC docs (core concepts, Python basics), Protobuf docs — ссылки в шапке.