.NET istemcisiyle gRPC hizmetlerini çağırma
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.
Grpc.Net.Client NuGet paketinde bir .NET gRPC istemci kitaplığı bulunur. Bu belgede aşağıdakilerin nasıl yapılacağını açıklanmaktadır:
- gRPC hizmetlerini çağırmak için bir gRPC istemcisi yapılandırın.
- Tekli, sunucu akışlı, istemci akışlı ve çift yönlü akış yöntemlerine gRPC çağrıları yapın.
gRPC istemciyi yapılandırma
gRPC istemcileri, .proto
dosyalarından oluşturulan somut istemci türleridir. Somut gRPC istemcisi, .proto
dosyasındaki gRPC hizmetine karşılık gelen yöntemlere sahiptir. Örneğin, adlı Greeter
bir hizmet, hizmeti çağırma yöntemlerini içeren bir GreeterClient
tür oluşturur.
Bir kanaldan gRPC istemcisi oluşturulur. Bir kanal oluşturmak için kullanarak GrpcChannel.ForAddress
başlayın ve ardından gRPC istemcisi oluşturmak için kanalı kullanın:
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greet.GreeterClient(channel);
Kanal, gRPC hizmetine uzun süreli bir bağlantıyı temsil eder. Kanal oluşturulduğunda, hizmet çağırmayla ilgili seçeneklerle yapılandırılır. Örneğin, çağrı yapmak için kullanılan HttpClient
, ileti gönderme ve alma boyutu üst sınırı ve günlük kaydı GrpcChannelOptions
üzerinde belirtilebilir ve GrpcChannel.ForAddress
ile kullanılabilir. Seçeneklerin tam listesi için bkz . istemci yapılandırma seçenekleri.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var greeterClient = new Greet.GreeterClient(channel);
var counterClient = new Count.CounterClient(channel);
// Use clients to call gRPC services
TLS’yi yapılandırma
gRPC istemcisi, çağrılan hizmetle aynı bağlantı düzeyi güvenliğini kullanmalıdır. gRPC istemcisi Aktarım Katmanı Güvenliği (TLS), gRPC kanalı oluşturulduğunda yapılandırılır. Bir gRPC istemcisi bir hizmeti çağırdığında bir hata oluşturur ve kanalın ve hizmetin bağlantı düzeyi güvenliği eşleşmiyor.
GRPC kanalını TLS kullanacak şekilde yapılandırmak için sunucu adresinin ile https
başladığından emin olun. Örneğin, GrpcChannel.ForAddress("https://localhost:5001")
HTTPS protokollerini kullanır. gRPC kanalı, TLS tarafından güvenli bir bağlantıyı otomatik olarak belirler ve gRPC çağrıları yapmak için güvenli bir bağlantı kullanır.
İpucu
gRPC, TLS üzerinden istemci sertifikası kimlik doğrulamayı destekler. İstemci sertifikalarını gRPC kanalıyla yapılandırma hakkında bilgi için bkz . ASP.NET Core için gRPC'de kimlik doğrulaması ve yetkilendirme.
Güvenli olmayan gRPC hizmetlerini çağırmak için sunucu adresinin ile http
başladığından emin olun. Örneğin, GrpcChannel.ForAddress("http://localhost:5000")
HTTP protokollerini kullanır. .NET Core 3.1'de, .NET istemcisiyle güvenli olmayan gRPC hizmetlerini çağırmak için ek yapılandırma gerekir.
İstemci performansı
Kanal ve istemci performansı ve kullanımı:
- Kanal oluşturmak pahalı bir işlem olabilir. gRPC çağrıları için bir kanalı yeniden kullanarak performans avantajları elde edebilirsiniz.
- Kanal, sunucu bağlantılarını yönetir. Bağlantı kapatılır veya kaybolursa, bir sonraki gRPC çağrısı yapıldığında kanal otomatik olarak yeniden bağlanır.
- gRPC istemcileri kanallarla oluşturulur. gRPC istemcileri basit nesnelerdir ve önbelleğe alınması veya yeniden kullanılması gerekmez.
- Farklı istemci türleri dahil olmak üzere bir kanaldan birden çok gRPC istemcisi oluşturulabilir.
- Kanaldan oluşturulan bir kanal ve istemciler birden çok iş parçacığı tarafından güvenle kullanılabilir.
- Kanaldan oluşturulan istemciler birden çok eşzamanlı arama yapabilir.
GrpcChannel.ForAddress
gRPC istemcisi oluşturmak için tek seçenek değildir. bir ASP.NET Core uygulamasından gRPC hizmetlerini çağırıyorsanız gRPC istemci fabrikası tümleştirmesini göz önünde bulundurun. ile HttpClientFactory
gRPC tümleştirmesi, gRPC istemcileri oluşturmaya merkezi bir alternatif sunar.
gRPC yöntemlerini çağırırken, zaman uyumsuz ile zaman uyumsuz programlama kullanmayı tercih edin vebekleyin.
Task.Result
veya Task.Wait()
gibi bloklama yöntemleri kullanarak gRPC çağrıları yapmak, diğer görevlerin bir iş parçacığını kullanmasını önler. Bu, iş parçacığı havuzunun tükenmesi ve düşük performansa neden olabilir. Bu, uygulamanın bir kilitlenmeyle donmasına neden olabilir. Daha fazla bilgi için bkz. istemci uygulamalarında zaman uyumsuz çağrılar.
gRPC çağrıları yapma
gRPC çağrısı, istemcide bir yöntem çağrılarak başlatılır. gRPC istemcisi, ileti serileştirmeyi işler ve gRPC çağrısını doğru hizmete yönlendirir.
gRPC'nin farklı yöntem türleri vardır. Bir gRPC çağrısı yapmak için istemcinin nasıl kullanıldığı, çağrılan yöntemin türüne bağlıdır. gRPC yöntem türleri şunlardır:
- Tekil
- Sunucudan akış
- İstemci akışı
- çift yönlü akış
Tekli arama
Üniter bir çağrı, istemcinin istek iletisi göndermesiyle başlar. Hizmet tamamlandığında bir yanıt iletisi döndürülür.
var client = new Greet.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = "World" });
Console.WriteLine("Greeting: " + response.Message);
// Greeting: Hello World
.proto
dosyasındaki her bir tekli hizmet yöntemi, somut gRPC istemci türünde, yöntemi çağırmak için iki .NET yöntemiyle sonuçlanır: biri zaman uyumsuz bir yöntem, diğeri ise engelleme yöntemi. Örneğin, GreeterClient
üzerinde SayHello
çağırmanın iki yolu vardır:
-
GreeterClient.SayHelloAsync
-Greeter.SayHello
hizmetini asenkron olarak çağırır. Beklenebilir. -
GreeterClient.SayHello
-Greeter.SayHello
hizmetini çağırır ve tamamlanana kadar bloke eder. Zaman uyumsuz kodda kullanmayın. Performans ve güvenilirlik sorunlarına neden olabilir.
Daha fazla bilgi için bkz. istemci uygulamalarında zaman uyumsuz çağrılar.
Sunucu akış çağrısı
Sunucu akış çağrısı, istemcinin istek iletisi göndermesiyle başlar.
ResponseStream.MoveNext()
hizmetten canlı yayımlanan iletileri okur.
ResponseStream.MoveNext()
false
'i döndürdüğünde, sunucu akış çağrısı tamamlanır.
var client = new Greet.GreeterClient(channel);
using var call = client.SayHellos(new HelloRequest { Name = "World" });
while (await call.ResponseStream.MoveNext())
{
Console.WriteLine("Greeting: " + call.ResponseStream.Current.Message);
// "Greeting: Hello World" is written multiple times
}
C# 8 veya üzerini kullanırken, await foreach
söz dizimi iletileri okumak için kullanılabilir.
IAsyncStreamReader<T>.ReadAllAsync()
Uzantı yöntemi, yanıt akışındaki tüm iletileri okur:
var client = new Greet.GreeterClient(channel);
using var call = client.SayHellos(new HelloRequest { Name = "World" });
await foreach (var response in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine("Greeting: " + response.Message);
// "Greeting: Hello World" is written multiple times
}
Sunucu akış çağrısı başlatıldığında döndürülen tür IDisposable
uygular. Durdurulmasını ve tüm kaynakların temizlendiğinden emin olmak için her zaman bir akış çağrısı atın.
İstemci akış çağrısı
İstemci akış çağrısı, istemci ileti göndermeden başlar. Müşteri, RequestStream.WriteAsync
ile mesaj göndermeyi seçebilir. İstemci ileti göndermeyi bitirdiğinde, RequestStream.CompleteAsync()
hizmete bildirmek için çağrılmalıdır. Hizmet bir yanıt iletisi döndürdüğünde çağrı tamamlanır.
var client = new Counter.CounterClient(channel);
using var call = client.AccumulateCount();
for (var i = 0; i < 3; i++)
{
await call.RequestStream.WriteAsync(new CounterRequest { Count = 1 });
}
await call.RequestStream.CompleteAsync();
var response = await call;
Console.WriteLine($"Count: {response.Count}");
// Count: 3
İstemci akış çağrısı başlatıldığında döndürülen tür IDisposable
uygular. Durdurulmasını ve tüm kaynakların temizlendiğinden emin olmak için her zaman bir akış çağrısı atın.
çift yönlü akış çağrısı
çift yönlü akış çağrısı, istemci ileti göndermeden başlar. İstemci RequestStream.WriteAsync
ile mesaj göndermeyi seçebilir. Hizmetten akışı yapılan iletilere ResponseStream.MoveNext()
veya ResponseStream.ReadAllAsync()
ile erişilebilir. Çift yönlü akış çağrısı, ResponseStream
artık ileti göndermediğinde tamamlanır.
var client = new Echo.EchoClient(channel);
using var call = client.Echo();
Console.WriteLine("Starting background task to receive messages");
var readTask = Task.Run(async () =>
{
await foreach (var response in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine(response.Message);
// Echo messages sent to the service
}
});
Console.WriteLine("Starting to send messages");
Console.WriteLine("Type a message to echo then press enter.");
while (true)
{
var result = Console.ReadLine();
if (string.IsNullOrEmpty(result))
{
break;
}
await call.RequestStream.WriteAsync(new EchoMessage { Message = result });
}
Console.WriteLine("Disconnecting");
await call.RequestStream.CompleteAsync();
await readTask;
En iyi performans için ve istemci ve hizmetteki gereksiz hataları önlemek için çift yönlü akış çağrılarını düzgün bir şekilde tamamlamayı deneyin. Sunucu istek akışını okumayı bitirdiğinde ve istemci yanıt akışını okumayı bitirdiğinde çift yönlü bir çağrı düzgün bir şekilde tamamlar. Yukarıdaki örnek çağrı, düzgün bir şekilde biten çift yönlü bir çağrı örneğidir. Çağrıda istemci:
- Yeni bir çift yönlü akış çağrısını,
EchoClient.Echo
çağrısı yaparak başlatır. - kullanarak
ResponseStream.ReadAllAsync()
hizmetten gelen iletileri okumak için bir arka plan görevi oluşturur. - ile
RequestStream.WriteAsync
sunucuya ileti gönderir. - ile
RequestStream.CompleteAsync()
ileti göndermeyi bitirdiğini sunucuya bildirir. - Arka plan görevi tüm gelen iletileri okuyana kadar bekler.
çift yönlü akış çağrısı sırasında, istemci ve hizmet istedikleri zaman birbirlerine ileti gönderebilir. İki yönlü bir çağrıyla etkileşim için en iyi istemci mantığı, hizmet mantığına bağlı olarak değişir.
Çift yönlü akış çağrısının başlatılmasıyla döndürülen tür, IDisposable
'yi uygular. Her zaman bir akış çağrısını sonlandırın veya yok edin, böylece durdurulduğundan ve tüm kaynakların temizlendiğinden emin olun.
gRPC üst bilgilerine eriş
gRPC çağrıları yanıt üst bilgilerini döndürür. HTTP yanıt üst bilgileri, döndürülen iletiyle ilgili olmayan bir çağrıyla ilgili ad/değer meta verilerini geçirir.
Başlıklara, bir meta veri koleksiyonu döndüren ResponseHeadersAsync
kullanılarak erişilebilir. Üst bilgiler genellikle yanıt iletisiyle döndürülür; Bu nedenle, onları beklemelisiniz.
var client = new Greet.GreeterClient(channel);
using var call = client.SayHelloAsync(new HelloRequest { Name = "World" });
var headers = await call.ResponseHeadersAsync;
var myValue = headers.GetValue("my-trailer-name");
var response = await call.ResponseAsync;
ResponseHeadersAsync
Kullanım:
- Üst bilgi koleksiyonunu almak için
ResponseHeadersAsync
sonucunu beklemelisiniz. -
ResponseAsync
'ye (veya akış sırasında yanıt akışına) daha önce erişilmesi gerekmez. Bir yanıt döndürüldüyse,ResponseHeadersAsync
anında üst bilgileri döndürür. - Bağlantı hatası veya sunucu hatası varsa ve gRPC çağrısı için üst bilgiler döndürülmezse bir istisna fırlatır.
Access gRPC fragmanları
gRPC çağrıları yanıt fragmanlarını döndürebilir. Çağrı hakkında ad/değer meta verileri sağlamak için römorklar kullanılır. Trailer'lar, HTTP üst bilgilerine benzer işlevsellik sağlar, ancak çağrının sonunda alınır.
Fragmanlara, GetTrailers()
kullanılarak erişilebilir ve bu da bir meta veri koleksiyonu döndürür. Römorklar yanıt tamamen tamamlandıktan sonra geri döndürülür. Bu nedenle, fragmanlara erişmeden önce tüm yanıt iletilerini beklemeniz gerekir.
Çağrılmadan önce ResponseAsync
tek yönlü ve istemci akış çağrıları beklemelidir GetTrailers()
.
var client = new Greet.GreeterClient(channel);
using var call = client.SayHelloAsync(new HelloRequest { Name = "World" });
var response = await call.ResponseAsync;
Console.WriteLine("Greeting: " + response.Message);
// Greeting: Hello World
var trailers = call.GetTrailers();
var myValue = trailers.GetValue("my-trailer-name");
Sunucu ve çift yönlü akış çağrılarının, GetTrailers()
çağrılmadan önce yanıt akışını beklemeyi bitirmesi gerekir.
var client = new Greet.GreeterClient(channel);
using var call = client.SayHellos(new HelloRequest { Name = "World" });
await foreach (var response in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine("Greeting: " + response.Message);
// "Greeting: Hello World" is written multiple times
}
var trailers = call.GetTrailers();
var myValue = trailers.GetValue("my-trailer-name");
Römorklar RpcException
dan da erişilebilir. Bir hizmet, geçerli olmayan bir gRPC durumuyla birlikte treyleri döndürebilir. Bu durumda, fragmanlar gRPC istemcisi tarafından oluşturulan özel durumdan alınır:
var client = new Greet.GreeterClient(channel);
string myValue = null;
try
{
using var call = client.SayHelloAsync(new HelloRequest { Name = "World" });
var response = await call.ResponseAsync;
Console.WriteLine("Greeting: " + response.Message);
// Greeting: Hello World
var trailers = call.GetTrailers();
myValue = trailers.GetValue("my-trailer-name");
}
catch (RpcException ex)
{
var trailers = ex.Trailers;
myValue = trailers.GetValue("my-trailer-name");
}
Son teslim tarihini yapılandırma
Bir aramanın ne kadar süreyle çalışabileceğine ilişkin bir üst sınır sağladığından gRPC arama son tarihini yapılandırmanız önerilir. Hatalı davranan hizmetlerin sonsuza kadar çalışmasını ve sunucu kaynaklarının tükenmesini engeller. Son tarihler, güvenilir uygulamalar oluşturmak için kullanışlı bir araçtır.
CallOptions.Deadline
'yi bir gRPC çağrısı için son tarih belirlemek üzere yapılandırın.
var client = new Greet.GreeterClient(channel);
try
{
var response = await client.SayHelloAsync(
new HelloRequest { Name = "World" },
deadline: DateTime.UtcNow.AddSeconds(5));
// Greeting: Hello World
Console.WriteLine("Greeting: " + response.Message);
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.DeadlineExceeded)
{
Console.WriteLine("Greeting timeout.");
}
Daha fazla bilgi için bkz. Son tarihler ve iptal özelliklerine sahip güvenilir gRPC hizmetleri.
Ek kaynaklar
ASP.NET Core