.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 8 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ışı, istemci akışı 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 çevrilen 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, HttpClient
çağrı yapmak için kullanılan, ileti gönderme ve alma boyutu üst sınırı ve günlük kaydı üzerinde GrpcChannelOptions
belirtilebilir ve ile GrpcChannel.ForAddress
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.
Not
ile Grpc.Net.Client
HTTP/2 üzerinden gRPC çağrısı şu anda Xamarin'de desteklenmiyor. Gelecekteki bir Xamarin sürümünde HTTP/2 desteğini geliştirmek için çalışıyoruz. Grpc.Core ve gRPC-Web , bugün çalışan uygulanabilir alternatiflerdir.
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. İstemcinin gRPC çağrısı yapmak için nasıl kullanıldığı, adlı yöntemin türüne bağlıdır. gRPC yöntem türleri şunlardır:
- Birli
- Sunucu akışı
- İstemci akışı
- çift yönlü akış
Birli arama
Birli arama, 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
Dosyadaki .proto
her bir tekli hizmet yöntemi, yöntemini çağırmak için somut gRPC istemci türünde iki .NET yöntemiyle sonuçlanır: zaman uyumsuz bir yöntem ve bir engelleme yöntemi. Örneğin, öğesini GreeterClient
çağırmanın SayHello
iki yolu vardır:
GreeterClient.SayHelloAsync
- hizmeti zaman uyumsuz olarak çağırırGreeter.SayHello
. Beklenebilir.GreeterClient.SayHello
- tamamlanana kadar hizmeti ve blokları çağırırGreeter.SayHello
. Zaman uyumsuz kodda kullanmayın.
Sunucu akış çağrısı
Sunucu akış çağrısı, istemcinin istek iletisi göndermesiyle başlar. ResponseStream.MoveNext()
hizmetten akışı yapılan iletileri okur. döndürdüğünde ResponseStream.MoveNext()
false
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ının başlatılmasından döndürülen tür uygular IDisposable
. 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. İstemci ile RequestStream.WriteAsync
ileti 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ının başlatılmasından döndürülen tür uygular IDisposable
. 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 ile RequestStream.WriteAsync
ileti göndermeyi seçebilir. Hizmetten akışı yapılan iletilere veya ResponseStream.ReadAllAsync()
ile ResponseStream.MoveNext()
erişilebilir. çift yönlü akış çağrısı, artık ileti olmadığında tamamlanır ResponseStream
.
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:
- çağrısı
EchoClient.Echo
yaparak yeni bir çift yönlü akış çağrısı 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ından döndürülen tür uygular IDisposable
. Durdurulmasını ve tüm kaynakların temizlendiğinden emin olmak için her zaman bir akış çağrısı atın.
Access gRPC üst bilgileri
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.
Üst bilgiler, meta veri koleksiyonunu döndüren kullanılarak ResponseHeadersAsync
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 sonucunun
ResponseHeadersAsync
beklenmelidir. - Daha önce
ResponseAsync
(veya akış sırasında yanıt akışına) erişilmesi gerekmez. Bir yanıt döndürüldüyse,ResponseHeadersAsync
anında üst bilgileri döndürür. - Bağlantı veya sunucu hatası varsa ve gRPC çağrısı için üst bilgiler döndürülmezse bir özel durum oluşturur.
Access gRPC fragmanları
gRPC çağrıları yanıt fragmanlarını döndürebilir. Fragmanlar, bir çağrı hakkında ad/değer meta verileri sağlamak için kullanılır. Fragmanlar HTTP üst bilgilerine benzer işlevler sağlar, ancak çağrının sonunda alınır.
Fragmanlara, meta veri koleksiyonunu döndüren kullanılarak GetTrailers()
erişilebilir. Römorklar yanıt tamamlandıktan sonra döndürülür. Bu nedenle, fragmanlara erişmeden önce tüm yanıt iletilerini beklemeniz gerekir.
çağrılmadan önce GetTrailers()
birli ve istemci akış çağrıları beklemelidirResponseAsync
:
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 çağrıdan GetTrailers()
ö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ömorklara uygulamasından RpcException
da erişilebilir. Bir hizmet, römorkları Tamam olmayan gRPC durumuyla birlikte 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 tarihi 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.
gRPC çağrısı için son tarih ayarlamak üzere yapılandırın CallOptions.Deadline
:
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 ile güvenilir gRPC hizmetleri.
Ek kaynaklar
ASP.NET Core