API Tasarımı & Gerçek Zamanlı İletişim 4 dk okuma 7 okunma

gRPC ile Streaming: Server, Client ve Bidirectional Streaming

gRPC, HTTP/2 üzerinde dört iletişim modeli sunar: unary, server streaming, client streaming ve bidirectional streaming. Streaming, büyük veri kümelerini parça parça taşımak ve gerçek zamanlı etkileşim sağlamak için idealdir. .NET'te IAsyncEnumerable, IServerStreamWriter ve IAsyncStreamReader ile uygulanır; ancak tarayıcı desteği gRPC-Web ile sınırlıdır (client/bidirectional streaming yoktur).

gRPC ile Streaming: Server, Client ve Bidirectional Streaming

gRPC ile Streaming: Server, Client ve Bidirectional Streaming

gRPC, HTTP/2'nin çoklama (multiplexing) ve akış (streaming) yeteneklerini kullanarak, geleneksel istek-yanıt modelinin ötesine geçen dört iletişim deseni sunar. Streaming, büyük veri kümelerini parça parça taşımak, canlı veri akışı sağlamak ve gerçek zamanlı etkileşim kurmak için güçlü bir araçtır. Bu yazıda, üç streaming modelini ve .NET'teki uygulamalarını ele alacağız.


1. Dört İletişim Modeli

Model Açıklama Kullanım Alanı
Unary Klasik istek-yanıt CRUD işlemleri
Server Streaming İstemci bir istek gönderir; sunucu bir dizi yanıt döner Canlı veri akışı, büyük veri kümeleri
Client Streaming İstemci bir dizi istek gönderir; sunucu tek yanıt döner Dosya yükleme, toplu veri gönderimi
Bidirectional Streaming Her iki taraf da bağımsız olarak akış gönderir Sohbet, oyun, gerçek zamanlı işbirliği

2. Proto Tanımlamaları

Streaming, .proto dosyasında stream anahtar kelimesiyle tanımlanır:

protobuf

service StreamService {
  rpc GetStream (Request) returns (stream Response);        // Server streaming
  rpc UploadStream (stream Request) returns (Response);     // Client streaming
  rpc Chat (stream Request) returns (stream Response);      // Bidirectional
}

3. Server Streaming: Sunucudan Sürekli Akış

Sunucu, tek bir isteğe karşılık bir dizi yanıt döner. İstemci, yanıtları geldikçe işler.

Sunucu Tarafı (.NET):

csharp

public override async Task GetStream(
    Request request,
    IServerStreamWriter<Response> responseStream,
    ServerCallContext context)
{
    for (int i = 0; i < 10; i++)
    {
        // İptal kontrolü: istemci bağlantıyı kestiyse dur
        if (context.CancellationToken.IsCancellationRequested)
            break;

        await responseStream.WriteAsync(new Response
        {
            Id = i,
            Message = $"Mesaj {i}: {request.Message}"
        });

        await Task.Delay(500);
    }
}

İstemci Tarafı (.NET):

csharp

using var call = client.GetStream(new Request { Message = "Merhaba" });

await foreach (var response in call.ResponseStream.ReadAllAsync())
{
    Console.WriteLine($"Alındı: {response.Message}");
}

Kullanım Alanları: Canlı borsa verisi, log takibi, büyük veri kümelerinin parça parça transferi.


4. Client Streaming: İstemciden Toplu Akış

İstemci, bir dizi istek gönderir; sunucu hepsini aldıktan sonra tek bir yanıt döner.

Sunucu Tarafı (.NET):

csharp

public override async Task<Response> UploadStream(
    IAsyncStreamReader<Request> requestStream,
    ServerCallContext context)
{
    int count = 0;

    await foreach (var request in requestStream.ReadAllAsync())
    {
        count++;
        // Her isteği işle (ör. dosya parçasını diske yaz)
    }

    return new Response { Message = $"Toplam {count} istek alındı." };
}

İstemci Tarafı (.NET):

csharp

using var call = client.UploadStream();

for (int i = 0; i < 10; i++)
{
    await call.RequestStream.WriteAsync(new Request { Message = $"Parça {i}" });
}

await call.RequestStream.CompleteAsync();
var response = await call.ResponseAsync;

Kullanım Alanları: Dosya yükleme (chunk'lı), telemetri toplama, toplu veri gönderimi.


5. Bidirectional Streaming: Karşılıklı Etkileşim

Her iki taraf da bağımsız olarak akış gönderir ve alır. Gerçek zamanlı, etkileşimli uygulamalar için idealdir.

Sunucu Tarafı (.NET):

csharp

public override async Task Chat(
    IAsyncStreamReader<Request> requestStream,
    IServerStreamWriter<Response> responseStream,
    ServerCallContext context)
{
    await foreach (var request in requestStream.ReadAllAsync())
    {
        await responseStream.WriteAsync(new Response
        {
            Message = $"Echo: {request.Message}"
        });
    }
}

İstemci Tarafı (.NET):

csharp

using var call = client.Chat();

// Sunucudan gelenleri dinleyen görev
var readTask = Task.Run(async () =>
{
    await foreach (var response in call.ResponseStream.ReadAllAsync())
    {
        Console.WriteLine($"Sunucu: {response.Message}");
    }
});

// İstemciden sunucuya mesaj gönder
for (int i = 0; i < 5; i++)
{
    await call.RequestStream.WriteAsync(new Request { Message = $"Mesaj {i}" });
    await Task.Delay(300);
}

await call.RequestStream.CompleteAsync();
await readTask;

Kullanım Alanları: Sohbet uygulamaları, çok oyunculu oyunlar, gerçek zamanlı işbirliği araçları.


6. Streaming'de Dikkat Edilmesi Gerekenler

  • İptal (Cancellation): Uzun süren akışlarda context.CancellationToken kontrol edilmelidir; aksi halde kaynaklar boşa tüketilir.

  • Akış Kontrolü (Flow Control): HTTP/2, akış kontrolü ile tampon taşmasını önler; ancak sunucu, istemciden hızlı veri gönderirse gecikme yaşanabilir.

  • Hata Yönetimi: Akış sırasında hata oluşursa RpcException fırlatılır ve akış sonlanır.

  • Mesaj Boyutu: Varsayılan maksimum mesaj boyutu 4MB'dir; büyük mesajlar için MaxReceiveMessageSize ayarlanmalıdır.


7. Tarayıcı Desteği: gRPC-Web Sınırlaması

gRPC-Web, tarayıcıdan gRPC'ye erişim sağlar; ancak client streaming ve bidirectional streaming desteklenmez. Yalnızca unary ve server streaming kullanılabilir. Bu nedenle, tarayıcı tabanlı gerçek zamanlı uygulamalarda WebSocket veya SignalR gibi alternatifler değerlendirilmelidir.


8. Ne Zaman Hangi Model?

Senaryo Öneri
Tek istek, tek yanıt Unary
Sunucudan sürekli veri akışı Server Streaming
Toplu veri gönderimi (dosya yükleme) Client Streaming
Karşılıklı, gerçek zamanlı iletişim Bidirectional Streaming
Tarayıcıdan gerçek zamanlı iletişim WebSocket / SignalR (gRPC-Web sınırlı)

Sonuç

gRPC streaming, modern dağıtık sistemlerde büyük veri transferi ve gerçek zamanlı iletişim için güçlü bir araçtır. Server streaming, sunucudan sürekli veri akışı; client streaming, toplu veri gönderimi; bidirectional streaming ise karşılıklı etkileşim için idealdir. .NET'te IAsyncEnumerable, IServerStreamWriter ve IAsyncStreamReader ile bu modeller kolayca uygulanır. Ancak tarayıcı desteğinin sınırlı olduğunu ve akış kontrolü, iptal yönetimi gibi konulara dikkat edilmesi gerektiğini unutmamak gerekir. Unutmayın: Streaming, "her şeyi tek seferde göndermek" yerine "doğru parçayı doğru zamanda göndermek" sanatıdır.

Tüm yazılar Soru ya da yorumun mu var? Yaz