gRPC Nedir ve .NET ile Nasıl Kullanılır?

Furkan SARIKAYA
9 min readJul 30, 2024

--

gRPC Nedir?

gRPC, Google tarafından geliştirilen, modern, açık kaynaklı ve yüksek performanslı bir uzaktan prosedür çağrısı (Remote Procedure Call — RPC) çerçevesidir. gRPC, istemci-sunucu uygulamaları arasında iletişimi kolaylaştırır ve farklı dillerde yazılmış uygulamaların birbiriyle etkileşim kurmasına olanak tanır. gRPC, HTTP/2 üzerinde çalışır ve Protobuf (Protocol Buffers) adlı hafif ve hızlı bir serileştirme formatını kullanır.

gRPC’nin Avantajları

  • Yüksek Performans: HTTP/2 protokolü ve Protobuf sayesinde düşük gecikme süresi ve yüksek aktarım hızı sunar.
  • Çoklu Dil Desteği: gRPC, C#, Java, Python, Go, Ruby, C++, Node.js ve daha birçok dilde kullanılabilir.
  • Kolay Versiyonlama: Protobuf sayesinde API’lerin versiyonlanması kolaydır ve geriye dönük uyumluluk sağlanabilir.
  • Tam Çift Yönlü İletişim: HTTP/2'nin sunduğu tam çift yönlü iletişim desteği ile istemci ve sunucu arasında asenkron veri akışı sağlanabilir.
  • Güvenlik: TLS/SSL ile güvenli iletişim sağlar.

gRPC Nasıl Kullanılır?

gRPC’yi kullanmak için aşağıdaki adımları izleyebilirsiniz:

1. Protobuf Tanımı

Protobuf (Protocol Buffers), Google tarafından geliştirilen, dil ve platform bağımsız bir veri serileştirme formatıdır. Protobuf tanımı, gRPC hizmetlerini ve bu hizmetlerin kullandığı mesaj türlerini tanımlar.

Protobuf Tanımı:

syntax = "proto3";

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

Detaylı Açıklama:

  1. syntax = “proto3”; Bu satır, Protobuf tanım dosyasının hangi sürümünü kullandığınızı belirtir. “proto3”, Protobuf’un üçüncü sürümünü ifade eder ve genellikle gRPC ile kullanılır.
  2. service Greeter { … } service anahtar kelimesi, bir gRPC hizmetini tanımlar. Greeter, bu hizmetin adıdır. Bu hizmetin içinde, çağrılabilecek RPC yöntemleri tanımlanır.
  3. rpc SayHello (HelloRequest) returns (HelloReply); rpc anahtar kelimesi, bir RPC yöntemini tanımlar. SayHello, bu yöntemin adıdır. (HelloRequest), bu yöntemin girdi mesaj türüdür. Yani, istemci bu yöntemi çağırırken bir HelloRequest mesajı gönderecektir. returns (HelloReply);, bu yöntemin çıktı mesaj türüdür. Yani, sunucu bu yöntemi işlediğinde bir HelloReply mesajı döndürecektir.
  4. message HelloRequest { … } message anahtar kelimesi, bir Protobuf mesaj türünü tanımlar. HelloRequest, bu mesaj türünün adıdır. Bu tür, RPC yöntemi için gerekli olan girdi verilerini içerir. { string name = 1; }, bu mesajın içeriğini tanımlar. string, alanın veri tipini belirtir. name, alanın adıdır. = 1, bu alanın numarasını belirtir. Alan numaraları, mesajın serileştirilmiş halindeki konumlarını belirler ve Protobuf'un geriye dönük uyumluluk sağlayabilmesine yardımcı olur.
  5. message HelloReply { … } message anahtar kelimesi, bir başka Protobuf mesaj türünü tanımlar. HelloReply, bu mesaj türünün adıdır. Bu tür, RPC yöntemi tarafından döndürülecek olan çıktı verilerini içerir. { string message = 1; }, bu mesajın içeriğini tanımlar. string, alanın veri tipini belirtir. message, alanın adıdır. = 1, bu alanın numarasını belirtir.

Bu Protobuf tanımı, Greeter adında bir hizmeti ve bu hizmetin SayHello adında bir yöntemini tanımlar. SayHello yöntemi, bir HelloRequest mesajı alır ve bir HelloReply mesajı döndürür. HelloRequest mesajı, bir name alanına sahiptir ve HelloReply mesajı, bir message alanına sahiptir.

Kullanım Örneği

Sunucu Kodu:

Sunucu, GreeterService adında bir sınıf tanımlar ve bu sınıf, Greeter.GreeterBase sınıfından türetilir. Bu sınıf, Protobuf tanımındaki Greeter hizmetine karşılık gelir ve SayHello yöntemini uygular.

public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}

Bu örnekte, SayHello yöntemi, istemciden bir HelloRequest mesajı alır ve bir HelloReply mesajı döndürür. Yanıt mesajı, Hello kelimesi ile istemcinin gönderdiği adı birleştirir.

İstemci Kodu:

İstemci, sunucuya bir HelloRequest mesajı gönderir ve bir HelloReply mesajı alır.

var channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
var client = new Greeter.GreeterClient(channel);

var reply = client.SayHello(new HelloRequest { Name = "World" });

Console.WriteLine("Greeting: " + reply.Message);

channel.ShutdownAsync().Wait();

Bu örnekte, istemci SayHello yöntemini çağırır, bir HelloRequest mesajı gönderir ve sunucudan gelen HelloReply mesajını alır.

2. Protobuf Dosyasını Derleme

Protobuf dosyasını, hedef dil için derleyerek istemci ve sunucu kodlarını oluşturabilirsiniz. .NET için, Grpc.Tools paketini kullanarak bu işlemi gerçekleştirebilirsiniz.

<ItemGroup>
<Protobuf Include="Protos\\greeter.proto" GrpcServices="Server" />
</ItemGroup>

3. Sunucu Uygulaması

Gereksinimler

  • .NET SDK (En az .NET 6 veya daha yeni bir sürüm)
  • Bir IDE (Visual Studio, Visual Studio Code veya Rider)

Adım 1: Yeni Bir .NET gRPC Projesi Oluşturma

İlk olarak, yeni bir gRPC projesi oluşturacağız. Bunun için terminal veya komut istemcisini kullanarak aşağıdaki komutu çalıştırın:

dotnet new grpc -n GrpcGreeter

Bu komut, GrpcGreeter adında yeni bir gRPC projesi oluşturur. Oluşturulan proje, temel gRPC yapılandırmalarını ve örnek kodları içerir.

Adım 2: Proje Yapısını Anlama

Oluşturulan projede aşağıdaki dosya ve klasörler bulunur:

  • Program.cs: Uygulamanın giriş noktası.
  • appsettings.json: Uygulama ayarları.
  • Protos: Protobuf dosyalarını içeren klasör.
  • Services: gRPC hizmetlerini içeren klasör.

Adım 3: Protobuf Dosyasını Tanımlama

Protos klasöründe greet.proto adında bir dosya bulunur. Bu dosya, gRPC hizmetini ve mesajlarını tanımlar. Aşağıdaki gibi basit bir greet.proto dosyası tanımlayalım:

syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

package greet;

// Greeter service tanımı
service Greeter {
// Bir HelloRequest alır ve bir HelloReply döner
rpc SayHello (HelloRequest) returns (HelloReply);
}

// İstek mesajı
message HelloRequest {
string name = 1;
}

// Yanıt mesajı
message HelloReply {
string message = 1;
}

Bu dosya, Greeter adlı bir hizmeti ve SayHello adlı bir yöntemi tanımlar. SayHello yöntemi, bir HelloRequest mesajı alır ve bir HelloReply mesajı döner.

Adım 4: gRPC Hizmetini Uygulama

Şimdi, Services klasöründe GreeterService.cs adında bir dosya oluşturalım ve Greeter hizmetini uygulayalım:

using Grpc.Core;
using GrpcGreeter;

namespace GrpcGreeter.Services
{
public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}
}

Bu sınıf, Greeter.GreeterBase sınıfından türetilir ve SayHello yöntemini uygular. SayHello yöntemi, istemciden gelen HelloRequest mesajını alır ve HelloReply mesajı döner.

Adım 5: Sunucuyu Yapılandırma ve Çalıştırma

Son olarak, Program.cs dosyasını açalım ve sunucuyu yapılandıralım:

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

// gRPC hizmetini ekle
builder.Services.AddGrpc();

var app = builder.Build();

// gRPC hizmetlerini uç noktalarına bağla
app.MapGrpcService<GreeterService>();

app.MapGet("/", () => "gRPC çalışıyor. gRPC istemcisi ile iletişim kurun.");

app.Run();

Bu kod, gRPC hizmetini uygulamaya ekler ve GreeterService hizmetini yapılandırır.

Adım 6: Uygulamayı Çalıştırma

Terminal veya komut istemcisinde aşağıdaki komutu çalıştırarak uygulamayı başlatın:

dotnet run

Uygulama başarıyla başlatıldığında, konsolda gRPC çalışıyor. gRPC istemcisi ile iletişim kurun. mesajını görmelisiniz.

4. İstemci Uygulaması

Gereksinimler

  • .NET SDK (En az .NET 6 veya daha yeni bir sürüm)
  • Bir IDE (Visual Studio, Visual Studio Code veya Rider)

Adım 1: Yeni Bir .NET Konsol Uygulaması Oluşturma

İlk olarak, yeni bir .NET Konsol uygulaması oluşturacağız. Bunun için terminal veya komut istemcisini kullanarak aşağıdaki komutu çalıştırın:

dotnet new console -n GrpcGreeterClient

Bu komut, GrpcGreeterClient adında yeni bir konsol uygulaması oluşturur.

Adım 2: gRPC ve Protobuf Paketlerini Ekleyin

Oluşturduğunuz projeye gRPC ve Protobuf paketlerini eklemek için terminalde aşağıdaki komutları çalıştırın:

cd GrpcGreeterClient
dotnet add package Grpc.Net.Client
dotnet add package Grpc.Tools
dotnet add package Google.Protobuf

Bu paketler, gRPC istemcisi oluşturmak için gerekli olan bağımlılıkları içerir.

Adım 3: Protobuf Dosyasını Ekleyin

Proje dizininde Protos adında bir klasör oluşturun ve greet.proto dosyasını bu klasöre ekleyin. greet.proto dosyasının içeriği sunucu uygulamasındaki ile aynı olmalıdır:

syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

package greet;

// Greeter service tanımı
service Greeter {
// Bir HelloRequest alır ve bir HelloReply döner
rpc SayHello (HelloRequest) returns (HelloReply);
}

// İstek mesajı
message HelloRequest {
string name = 1;
}

// Yanıt mesajı
message HelloReply {
string message = 1;
}

Adım 4: csproj Dosyasını Güncelleyin

Projenizin .csproj dosyasını açın ve Protobuf dosyasının derlenmesini sağlamak için aşağıdaki öğeleri ekleyin:

<ItemGroup>
<Protobuf Include="Protos\\greet.proto" GrpcServices="Client" />
</ItemGroup>

Bu yapılandırma, Protobuf dosyasını istemci için gerekli C# koduna dönüştürecektir.

Adım 5: İstemci Kodunu Yazın

Program.cs dosyasını açın ve aşağıdaki kodu ekleyin:

using Grpc.Net.Client;
using grpcServer;

// gRPC kanalı oluşturma
var channel = GrpcChannel.ForAddress("https://localhost:7018");

// Greeter istemcisi oluşturma
var greetClient = new Greeter.GreeterClient(channel);

// Sunucuya istek gönderme
var reply = await greetClient.SayHelloAsync(new HelloRequest{Name = "Furkan"});

// Yanıtı yazdırma
Console.WriteLine($"Greeting : {reply.Message}");

Bu kod, gRPC sunucusuna bağlanır, SayHello yöntemini çağırır ve sunucudan gelen yanıtı konsola yazdırır.

Adım 6: SSL Sertifikası ile Çalışma (Opsiyonel)

Varsayılan olarak, gRPC istemcisi SSL/TLS kullanarak sunucuya bağlanır. Sunucu uygulaması, HTTPS üzerinden çalıştığı için istemcinin doğru SSL sertifikasına sahip olması gerekir. Geliştirme ortamında, sunucuya güvenmek için aşağıdaki komutu kullanarak SSL doğrulamasını devre dışı bırakabilirsiniz:

// gRPC kanalı oluşturma
var httpClientHandler = new HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;

using var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = httpClientHandler });

Bu kod, SSL doğrulamasını devre dışı bırakır. Üretim ortamında, bu yaklaşım güvenli değildir ve doğru SSL sertifikasını kullanmanız önerilir.

Adım 7: Uygulamayı Çalıştırma

Terminal veya komut istemcisinde aşağıdaki komutu çalıştırarak istemci uygulamasını başlatın:

dotnet run

Uygulama başarıyla çalıştığında, konsolda Greeting: Hello World mesajını görmelisiniz.

Örnek Kullanım Senaryoları

  • Mikroservis Mimarisi: gRPC, mikroservislerin birbirleriyle hızlı ve verimli bir şekilde iletişim kurmasını sağlar.
  • Gerçek Zamanlı İletişim: Çift yönlü veri akışı sayesinde anlık veri transferi gereken uygulamalarda kullanılabilir.
  • Çoklu Platform Desteği: Farklı dillerde yazılmış uygulamaların birbiriyle uyumlu çalışmasını sağlar.

gRPC’deki RPC Yaşam Döngüsü

gRPC, istemci-sunucu mimarisine dayalı olarak çalışan bir RPC (Remote Procedure Call) çerçevesidir. RPC yaşam döngüsü, istemci tarafından başlatılan bir çağrının sunucu tarafından işlenip sonuçlandırılmasını kapsar. gRPC’de bu süreç dört temel adımdan oluşur:

1. İstemci Çağrısı Başlatma

İstemci, gRPC istemci kütüphanesini kullanarak sunucuda tanımlı bir hizmeti çağırır. Bu aşamada istemci, gerekli parametreleri içeren bir istek mesajı oluşturur ve bu mesajı sunucuya gönderir.

2. İstek Gönderme

gRPC, istek mesajını Protobuf kullanarak serileştirir ve HTTP/2 protokolü üzerinden sunucuya gönderir. HTTP/2'nin sağladığı avantajlarla düşük gecikme süresi ve yüksek performans elde edilir.

3. Sunucu İsteği İşleme

Sunucu, gelen isteği alır ve ilgili hizmet metodunu çağırır. Bu işlem sırasında sunucu, istek mesajını Protobuf kullanarak yeniden oluşturur ve işleme başlar. İşlem tamamlandığında sunucu, yanıt mesajını oluşturur.

4. Yanıt Gönderme

Sunucu, yanıt mesajını Protobuf kullanarak serileştirir ve HTTP/2 üzerinden istemciye geri gönderir. İstemci, bu yanıtı alır ve sonuçları işler.

gRPC’deki Farklı RPC Türleri: Unary, Server Streaming, Client Streaming ve Bidirectional Streaming

gRPC, dağıtık sistemlerde yüksek performanslı ve verimli iletişim sağlamak için çeşitli RPC (Remote Procedure Call) türleri sunar.

1. Unary RPC

Tanım

Unary RPC, en basit ve en yaygın kullanılan RPC türüdür. İstemci, sunucuya bir istek gönderir ve sunucudan tek bir yanıt alır. Bu model, geleneksel fonksiyon çağrısına benzer şekilde çalışır.

Kullanım Örneği

Protobuf Tanımı:

syntax = "proto3";

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

Sunucu Kodu:

public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
}

İstemci Kodu:

var channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
var client = new Greeter.GreeterClient(channel);

var reply = client.SayHello(new HelloRequest { Name = "World" });

Console.WriteLine("Greeting: " + reply.Message);

channel.ShutdownAsync().Wait();

2. Server Streaming RPC

Tanım

Server Streaming RPC, istemcinin bir istek gönderdiği ve sunucunun bir dizi yanıt gönderdiği bir modeldir. İstemci, yanıtları akış olarak alır ve işlemeye devam eder.

Kullanım Örneği

Protobuf Tanımı:

syntax = "proto3";

service Greeter {
rpc ListFeatures (Rectangle) returns (stream Feature);
}

message Rectangle {
// Rectangle coordinates
}

message Feature {
string name = 1;
// Feature details
}

Sunucu Kodu:

public class GreeterService : Greeter.GreeterBase
{
public override async Task ListFeatures(Rectangle request, IServerStreamWriter<Feature> responseStream, ServerCallContext context)
{
foreach (var feature in GetFeatures(request))
{
await responseStream.WriteAsync(feature);
}
}

private IEnumerable<Feature> GetFeatures(Rectangle request)
{
// Features retrieval logic
}
}

İstemci Kodu:

var channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
var client = new Greeter.GreeterClient(channel);

var call = client.ListFeatures(new Rectangle());

await foreach (var feature in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine("Feature: " + feature.Name);
}

await channel.ShutdownAsync();

3. Client Streaming RPC

Tanım

Client Streaming RPC, istemcinin sunucuya bir dizi istek gönderdiği ve sunucunun bu isteklerin tamamlanmasını bekleyip tek bir yanıt döndürdüğü bir modeldir. İstemci, istekleri akış olarak sunucuya gönderir.

Kullanım Örneği

Protobuf Tanımı:

syntax = "proto3";

service Greeter {
rpc RecordRoute (stream Point) returns (RouteSummary);
}

message Point {
// Point coordinates
}

message RouteSummary {
int32 point_count = 1;
// Summary details
}

Sunucu Kodu:

public class GreeterService : Greeter.GreeterBase
{
public override async Task<RouteSummary> RecordRoute(IAsyncStreamReader<Point> requestStream, ServerCallContext context)
{
var summary = new RouteSummary();
while (await requestStream.MoveNext())
{
var point = requestStream.Current;
summary.PointCount++;
// Additional processing
}
return summary;
}
}

İstemci Kodu:

var channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
var client = new Greeter.GreeterClient(channel);

var call = client.RecordRoute();

foreach (var point in GetPoints())
{
await call.RequestStream.WriteAsync(point);
}

await call.RequestStream.CompleteAsync();

var summary = await call;
Console.WriteLine("Summary: " + summary.PointCount);

await channel.ShutdownAsync();

4. Bidirectional Streaming RPC

Tanım

Bidirectional Streaming RPC, istemcinin ve sunucunun bağımsız olarak veri gönderip alabildiği tam çift yönlü bir iletişim modelidir. Hem istemci hem de sunucu veri akışlarını asenkron olarak yönetir.

Kullanım Örneği

Protobuf Tanımı:

syntax = "proto3";

service Greeter {
rpc Chat (stream ChatMessage) returns (stream ChatMessage);
}

message ChatMessage {
string user = 1;
string message = 2;
}

Sunucu Kodu:

public class GreeterService : Greeter.GreeterBase
{
public override async Task Chat(IAsyncStreamReader<ChatMessage> requestStream, IServerStreamWriter<ChatMessage> responseStream, ServerCallContext context)
{
var responseTask = Task.Run(async () =>
{
await foreach (var message in requestStream.ReadAllAsync())
{
// Process incoming message and prepare response
await responseStream.WriteAsync(new ChatMessage
{
User = message.User,
Message = "Received: " + message.Message
});
}
});

await responseTask;
}
}

İstemci Kodu:

var channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
var client = new Greeter.GreeterClient(channel);

var call = client.Chat();

var sendTask = Task.Run(async () =>
{
foreach (var message in GetMessages())
{
await call.RequestStream.WriteAsync(new ChatMessage { User = "User", Message = message });
}
await call.RequestStream.CompleteAsync();
});

var receiveTask = Task.Run(async () =>
{
await foreach (var response in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine("Response: " + response.Message);
}
});

await Task.WhenAll(sendTask, receiveTask);

await channel.ShutdownAsync();

gRPC, çeşitli RPC türleri sunarak dağıtık sistemlerde esnek ve yüksek performanslı iletişim sağlar. Unary RPC, tek bir istek ve yanıt modelini sunarken; Server Streaming RPC, sunucunun bir dizi yanıt göndermesine olanak tanır. Client Streaming RPC, istemcinin bir dizi istek göndermesini sağlar ve sunucu bu isteklerin tamamlanmasını bekler. Bidirectional Streaming RPC ise istemci ve sunucu arasında tam çift yönlü iletişime izin verir.

Sonuç

gRPC, modern uygulamaların iletişim ihtiyaçlarını karşılamak için güçlü ve esnek bir çözüm sunar. Yüksek performans, çoklu dil desteği ve kolay versiyonlama gibi avantajları sayesinde, gRPC’yi projelerinizde kullanarak daha hızlı ve güvenli bir iletişim altyapısı oluşturabilirsiniz. Bu makalede, gRPC’nin temel özelliklerini ve nasıl kullanılacağını ele aldık. Kendi projelerinizde gRPC’yi denemekten çekinmeyin ve avantajlarından yararlanın.

Bu makale ile gRPC hakkında temel bilgileri ve kullanım yöntemlerini öğrenmiş oldunuz. Daha fazla bilgi ve detaylı dokümantasyon için gRPC’nin resmi sitesini ziyaret edebilirsiniz.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response