Wywoływanie usług gRPC przy użyciu klienta platformy .NETCall gRPC services with the .NET client

Biblioteka klienta .NET gRPC jest dostępna w pakiecie NuGet gRPC .NET. Client .A .NET gRPC client library is available in the Grpc.Net.Client NuGet package. W tym dokumencie wyjaśniono, jak:This document explains how to:

  • Skonfiguruj klienta gRPC do wywoływania usług gRPC.Configure a gRPC client to call gRPC services.
  • GRPC wywołania jednoargumentowe, przesyłania strumieniowego serwera, przesyłania strumieniowego klienta i dwukierunkowych metod przesyłania strumieniowego.Make gRPC calls to unary, server streaming, client streaming, and bi-directional streaming methods.

Konfigurowanie klienta gRPCConfigure gRPC client

gRPC klienci są konkretnymi typami klientów, które są generowane z plików * . proto.gRPC clients are concrete client types that are generated from *.proto files. Konkretny klient gRPC ma metody, które są tłumaczone na usługę gRPC w pliku * . proto .The concrete gRPC client has methods that translate to the gRPC service in the *.proto file. Na przykład wywołana usługa Greeter generuje GreeterClient Typ z metodami wywołania usługi.For example, a service called Greeter generates a GreeterClient type with methods to call the service.

Klient gRPC jest tworzony na podstawie kanału.A gRPC client is created from a channel. Uruchom GrpcChannel.ForAddress polecenie, aby utworzyć kanał, a następnie użyj kanału, aby utworzyć klienta gRPC:Start by using GrpcChannel.ForAddress to create a channel, and then use the channel to create a gRPC client:

var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greet.GreeterClient(channel);

Kanał reprezentuje długotrwałe połączenie z usługą gRPC.A channel represents a long-lived connection to a gRPC service. Po utworzeniu kanału jest on konfigurowany z opcjami związanymi z wywoływaniem usługi.When a channel is created, it is configured with options related to calling a service. Na przykład HttpClient używane do wykonywania wywołań, maksymalnego rozmiaru wysyłania i odbierania wiadomości oraz rejestrowania można określić GrpcChannelOptions i użyć z GrpcChannel.ForAddress .For example, the HttpClient used to make calls, the maximum send and receive message size, and logging can be specified on GrpcChannelOptions and used with GrpcChannel.ForAddress. Aby uzyskać pełną listę opcji, zobacz Opcje konfiguracji klienta.For a complete list of options, see client configuration options.

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

Konfigurowanie protokołu TLSConfigure TLS

Klient gRPC musi używać tego samego zabezpieczenia na poziomie połączenia co nazwana usługa.A gRPC client must use the same connection-level security as the called service. gRPC Client Transport Layer Security (TLS) jest konfigurowany podczas tworzenia kanału gRPC.gRPC client Transport Layer Security (TLS) is configured when the gRPC channel is created. Klient gRPC zgłasza błąd podczas wywoływania usługi, a zabezpieczenia na poziomie połączenia kanału i usługi nie są zgodne.A gRPC client throws an error when it calls a service and the connection-level security of the channel and service don't match.

Aby skonfigurować kanał gRPC do korzystania z protokołu TLS, upewnij się, że adres serwera zaczyna się od https .To configure a gRPC channel to use TLS, ensure the server address starts with https. Na przykład GrpcChannel.ForAddress("https://localhost:5001") używa protokołu HTTPS.For example, GrpcChannel.ForAddress("https://localhost:5001") uses HTTPS protocol. Kanał gRPC automatycznie negocjuje połączenie zabezpieczone przez protokół TLS i używa bezpiecznego połączenia do wykonywania wywołań gRPC.The gRPC channel automatically negotiates a connection secured by TLS and uses a secure connection to make gRPC calls.

Porada

gRPC obsługuje uwierzytelnianie certyfikatu klienta za pośrednictwem protokołu TLS.gRPC supports client certificate authentication over TLS. Informacje dotyczące konfigurowania certyfikatów klienta przy użyciu kanału gRPC można znaleźć w temacie Uwierzytelnianie i autoryzacja w programie gRPC for ASP.NET Core .For information on configuring client certificates with a gRPC channel, see Uwierzytelnianie i autoryzacja w programie gRPC for ASP.NET Core.

Aby wywoływać niezabezpieczone usługi gRPC, upewnij się, że adres serwera zaczyna się od http .To call unsecured gRPC services, ensure the server address starts with http. Na przykład GrpcChannel.ForAddress("http://localhost:5000") używa protokołu HTTP.For example, GrpcChannel.ForAddress("http://localhost:5000") uses HTTP protocol. W przypadku platformy .NET Core 3,1 lub nowszej dodatkowa konfiguracja jest wymagana do wywołania niezabezpieczonych usług gRPC z klientem platformy .NET.In .NET Core 3.1 or later, additional configuration is required to call insecure gRPC services with the .NET client.

Wydajność klientaClient performance

Wydajność i użycie kanału i klienta:Channel and client performance and usage:

  • Tworzenie kanału może być kosztowną operacją.Creating a channel can be an expensive operation. Użycie kanału dla wywołań gRPC zapewnia korzyści wynikające z wydajności.Reusing a channel for gRPC calls provides performance benefits.
  • gRPC klienci są tworzone za pomocą kanałów.gRPC clients are created with channels. gRPC klienci są obiektami lekkimi i nie muszą być buforowane ani ponownie używane.gRPC clients are lightweight objects and don't need to be cached or reused.
  • Wielu klientów gRPC można utworzyć na podstawie kanału, w tym różnych typów klientów.Multiple gRPC clients can be created from a channel, including different types of clients.
  • Kanał i klienci utworzeni z kanału mogą być bezpiecznie używani przez wiele wątków.A channel and clients created from the channel can safely be used by multiple threads.
  • Klienci utworzeni z kanału mogą wykonywać wiele jednoczesnych wywołań.Clients created from the channel can make multiple simultaneous calls.

GrpcChannel.ForAddress nie jest jedyną opcją tworzenia klienta gRPC.GrpcChannel.ForAddress isn't the only option for creating a gRPC client. W przypadku wywoływania usług gRPC z poziomu aplikacji ASP.NET Core należy wziąć pod uwagę integrację klienta gRPC.If calling gRPC services from an ASP.NET Core app, consider gRPC client factory integration. Integracja gRPC z programem HttpClientFactory oferuje scentralizowaną alternatywę do tworzenia klientów gRPC.gRPC integration with HttpClientFactory offers a centralized alternative to creating gRPC clients.

Uwaga

Wywoływanie gRPC za pośrednictwem protokołu HTTP/2 z Grpc.Net.Client nie jest obecnie obsługiwane w oprogramowaniu Xamarin.Calling gRPC over HTTP/2 with Grpc.Net.Client is currently not supported on Xamarin. Pracujemy nad ulepszeniem obsługi protokołu HTTP/2 w przyszłej wersji platformy Xamarin.We are working to improve HTTP/2 support in a future Xamarin release. GRPC. Core i GRPC-Web to żywotne alternatywy, które działają dzisiaj.Grpc.Core and gRPC-Web are viable alternatives that work today.

Utwórz wywołania gRPCMake gRPC calls

Wywołanie gRPC jest inicjowane przez wywołanie metody na kliencie.A gRPC call is initiated by calling a method on the client. Klient gRPC będzie obsługiwał serializację komunikatów i odnoszący się do wywołania gRPC do prawidłowej usługi.The gRPC client will handle message serialization and addressing the gRPC call to the correct service.

gRPC ma różne typy metod.gRPC has different types of methods. Sposób, w jaki klient jest używany do wykonywania wywołania gRPC, zależy od typu metody o nazwie.How the client is used to make a gRPC call depends on the type of method called. Typy metod gRPC są następujące:The gRPC method types are:

  • JednoargumentowyUnary
  • Przesyłanie strumieniowe serweraServer streaming
  • Przesyłanie strumieniowe klientaClient streaming
  • Dwukierunkowe przesyłanie strumienioweBi-directional streaming

Wywołanie jednoargumentoweUnary call

Wywołanie jednoargumentowe rozpoczyna się od klienta wysyłającego komunikat żądania.A unary call starts with the client sending a request message. Komunikat odpowiedzi jest zwracany po zakończeniu działania usługi.A response message is returned when the service finishes.

var client = new Greet.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = "World" });

Console.WriteLine("Greeting: " + response.Message);
// Greeting: Hello World

Każda Jednoargumentowa metoda usługi w pliku * . proto powoduje dwie metody .NET na konkretnym typie klienta gRPC do wywoływania metody: Metoda asynchroniczna i Metoda blokująca.Each unary service method in the *.proto file will result in two .NET methods on the concrete gRPC client type for calling the method: an asynchronous method and a blocking method. Na przykład istnieją GreeterClient dwa sposoby wywoływania SayHello :For example, on GreeterClient there are two ways of calling SayHello:

  • GreeterClient.SayHelloAsync -wywołuje Greeter.SayHello usługę asynchronicznie.GreeterClient.SayHelloAsync - calls Greeter.SayHello service asynchronously. Można oczekiwać.Can be awaited.
  • GreeterClient.SayHello -wywołuje Greeter.SayHello usługę i bloki do momentu ukończenia.GreeterClient.SayHello - calls Greeter.SayHello service and blocks until complete. Nie używaj w kodzie asynchronicznym.Don't use in asynchronous code.

Wywołanie przesyłania strumieniowego serweraServer streaming call

Wywołanie przesyłania strumieniowego serwera rozpoczyna się od klienta wysyłającego komunikat żądania.A server streaming call starts with the client sending a request message. ResponseStream.MoveNext() odczytuje komunikaty przesyłane strumieniowo z usługi.ResponseStream.MoveNext() reads messages streamed from the service. Wywołanie przesyłania strumieniowego serwera jest kompletne, gdy ResponseStream.MoveNext() zwraca false .The server streaming call is complete when ResponseStream.MoveNext() returns false.

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
}

W przypadku korzystania z języka C# 8 lub nowszego await foreach składnia może być używana do odczytywania wiadomości.When using C# 8 or later, the await foreach syntax can be used to read messages. IAsyncStreamReader<T>.ReadAllAsync()Metoda rozszerzająca odczytuje wszystkie komunikaty ze strumienia odpowiedzi:The IAsyncStreamReader<T>.ReadAllAsync() extension method reads all messages from the response stream:

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
}

Wywołanie przesyłania strumieniowego klientaClient streaming call

Wywołanie przesyłania strumieniowego klienta rozpoczyna się bez wysyłania komunikatu przez klienta.A client streaming call starts without the client sending a message. Klient może wysyłać wiadomości za pomocą polecenia RequestStream.WriteAsync .The client can choose to send messages with RequestStream.WriteAsync. Gdy klient zakończył wysyłanie komunikatów, RequestStream.CompleteAsync() powinien zostać wywołany w celu powiadomienia usługi.When the client has finished sending messages, RequestStream.CompleteAsync() should be called to notify the service. Wywołanie jest zakończone, gdy usługa zwróci komunikat odpowiedzi.The call is finished when the service returns a response message.

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

Dwukierunkowe wywołanie przesyłania strumieniowegoBi-directional streaming call

Dwukierunkowe wywołanie przesyłania strumieniowego rozpoczyna się bez wysyłania komunikatu przez klienta.A bi-directional streaming call starts without the client sending a message. Klient może wysyłać wiadomości za pomocą polecenia RequestStream.WriteAsync .The client can choose to send messages with RequestStream.WriteAsync. Komunikaty przesyłane strumieniowo z usługi są dostępne z ResponseStream.MoveNext() lub ResponseStream.ReadAllAsync() .Messages streamed from the service are accessible with ResponseStream.MoveNext() or ResponseStream.ReadAllAsync(). Dwukierunkowe wywołanie przesyłania strumieniowego jest kompletne, gdy ResponseStream nie ma więcej komunikatów.The bi-directional streaming call is complete when the ResponseStream has no more messages.

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;

Aby uzyskać najlepszą wydajność i uniknąć niepotrzebnych błędów w kliencie i usłudze, spróbuj bezpiecznie wykonać wywołania przesyłania strumieniowego dwukierunkowe.For best performance, and to avoid unnecessary errors in the client and service, try to complete bi-directional streaming calls gracefully. Wywołanie dwukierunkowe kończy się bezpiecznie, gdy serwer zakończył odczytywanie strumienia żądań, a klient zakończył odczytywanie strumienia odpowiedzi.A bi-directional call completes gracefully when the server has finished reading the request stream and the client has finished reading the response stream. Poprzednie przykładowe wywołanie to jeden przykład dwukierunkowego wywołania, które się zakończyło.The preceding sample call is one example of a bi-directional call that ends gracefully. W wywołaniu klient:In the call, the client:

  1. Uruchamia nowe dwukierunkowe wywołanie przesyłania strumieniowego przez wywołanie EchoClient.Echo .Starts a new bi-directional streaming call by calling EchoClient.Echo.
  2. Tworzy zadanie w tle do odczytywania wiadomości z usługi przy użyciu programu ResponseStream.ReadAllAsync() .Creates a background task to read messages from the service using ResponseStream.ReadAllAsync().
  3. Wysyła komunikaty do serwera przy użyciu programu RequestStream.WriteAsync .Sends messages to the server with RequestStream.WriteAsync.
  4. Powiadamia serwer, który zakończył wysyłanie komunikatów z programu RequestStream.CompleteAsync() .Notifies the server it has finished sending messages with RequestStream.CompleteAsync().
  5. Czeka, aż zadanie w tle odczytaje wszystkie wiadomości przychodzące.Waits until the background task has read all incoming messages.

W trakcie dwukierunkowego wywołania przesyłania strumieniowego klient i usługa mogą w dowolnym momencie wysyłać komunikaty do siebie.During a bi-directional streaming call, the client and service can send messages to each other at any time. Najlepsza logika klienta do współpracy z dwukierunkowym wywołaniem różni się w zależności od logiki usługi.The best client logic for interacting with a bi-directional call varies depending upon the service logic.

Dostęp do przyczep gRPCAccess gRPC trailers

wywołania gRPC mogą zwracać gRPC przyczep.gRPC calls may return gRPC trailers. przyczepy gRPC są używane do dostarczania metadanych nazw/wartości dotyczących wywołania.gRPC trailers are used to provide name/value metadata about a call. Przyczepy zapewniają podobną funkcjonalność do nagłówków HTTP, ale są odbierane na końcu wywołania.Trailers provide similar functionality to HTTP headers, but are received at the end of the call.

gRPC przyczep są dostępne przy użyciu GetTrailers() , która zwraca kolekcję metadanych.gRPC trailers are accessible using GetTrailers(), which returns a collection of metadata. Po zakończeniu odpowiedzi są zwracane przyczepy. w związku z tym przed uzyskaniem dostępu do przyczep należy oczekiwać wszystkich komunikatów odpowiedzi.Trailers are returned after the response is complete, therefore, you must await all response messages before accessing the trailers.

Wywołania jednoargumentowe i wywołanie przesyłania strumieniowego klienta muszą oczekiwać ResponseAsync przed wywołaniem GetTrailers() :Unary and client streaming calls must await ResponseAsync before calling 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");

Wywołania przesyłania strumieniowego serwera i dwukierunkowe muszą kończyć się oczekiwaniem przed wywołaniem strumienia odpowiedzi GetTrailers() :Server and bidirectional streaming calls must finish awaiting the response stream before calling GetTrailers():

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");

gRPC przyczepy są również dostępne z programu RpcException .gRPC trailers are also accessible from RpcException. Usługa może zwracać przyczepy ze stanem gRPC innym niż OK.A service may return trailers together with a non-OK gRPC status. W tej sytuacji przyczepy są pobierane z wyjątku zgłoszonego przez klienta gRPC:In this situation the trailers are retrieved from the exception thrown by the gRPC client:

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");
}

Konfigurowanie terminu ostatecznegoConfigure deadline

Zaleca się skonfigurowanie ostatecznego terminu wywołania gRPC, ponieważ zawiera on górny limit czasu, w którym można uruchomić wywołanie.Configuring a gRPC call deadline is recommended because it provides an upper limit on how long a call can run for. Usługa błędna uniemożliwia uruchamianie nieograniczonego i wyczerpania zasobów serwera.It stops misbehaving services from running forever and exhausting server resources. Terminy są przydatnym narzędziem do tworzenia niezawodnych aplikacji.Deadlines are a useful tool for building reliable apps.

Skonfiguruj, CallOptions.Deadline Aby ustawić ostateczny termin wywołania gRPC:Configure CallOptions.Deadline to set a deadline for a gRPC call:

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.");
}

Aby uzyskać więcej informacji, zobacz Niezawodne usługi gRPC z terminami i anulowaniem.For more information, see Niezawodne usługi gRPC z terminami i anulowaniem.

Dodatkowe zasobyAdditional resources