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

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:
- 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.
- 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. - 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 birHelloRequest
mesajı gönderecektir.returns (HelloReply);
, bu yöntemin çıktı mesaj türüdür. Yani, sunucu bu yöntemi işlediğinde birHelloReply
mesajı döndürecektir. - 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. - 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.