Стриминг: server, client, bidirectional

↑ 5.2 gRPC · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

Когда gRPC-стриминг оправдан и как правильно завершать поток.

Объяснение

ВидprotoПример
Unaryrpc A (Req) returns (Res)обычный запрос
Server streamingreturns (stream Res)подписка на события, выгрузка
Client streaming(stream Req) returns (Res)загрузка файла кусками
Bidirectional(stream Req) returns (stream Res)чат, телеметрия
// Server streaming
public override async Task Watch(WatchRequest req, IServerStreamWriter<OrderEvent> stream, ServerCallContext ctx)
{
    await foreach (var e in events.SubscribeAsync(ctx.CancellationToken))
        await stream.WriteAsync(new OrderEvent { Id = e.Id });
}
 
// Client
using var call = client.Watch(new WatchRequest());
await foreach (var e in call.ResponseStream.ReadAllAsync(ct))
    Console.WriteLine(e.Id);
 
// Client streaming
using var upload = client.Upload();
foreach (var chunk in chunks) await upload.RequestStream.WriteAsync(chunk);
await upload.RequestStream.CompleteAsync();
var result = await upload;

Нюансы и подводные камни

  • Стрим держит соединение: планируйте keepalive и переподключение.
  • Обрабатывайте ctx.CancellationToken, иначе поток продолжит работать после ухода клиента.
  • Обратное давление: медленный клиент замедляет WriteAsync; ограничивайте очередь.
  • Запись в один стрим из нескольких потоков одновременно недопустима.
  • Между балансировщиками длинные стримы могут обрываться: делайте idle-timeout и retry.

Практика

  1. Реализуйте загрузку файла клиентским стримом по 64 КБ.
  2. Сделайте server streaming уведомлений с переподключением клиента.
  3. Соберите чат на bidirectional streaming.

Вопросы с ответами

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