Chamar os serviços gRPC com o cliente .NETCall gRPC services with the .NET client

Uma biblioteca de cliente .NET gRPC está disponível no pacote NuGet gRPC .net. Client .A .NET gRPC client library is available in the Grpc.Net.Client NuGet package. Este documento explica como:This document explains how to:

  • Configure um cliente gRPC para chamar os serviços gRPC.Configure a gRPC client to call gRPC services.
  • Faça chamadas gRPC para métodos unários, transmissão de servidor, streaming de cliente e streaming bidirecional.Make gRPC calls to unary, server streaming, client streaming, and bi-directional streaming methods.

Configurar o cliente gRPCConfigure gRPC client

Os clientes gRPC são tipos de cliente concretos que são gerados a partir de arquivos * * . proto* .gRPC clients are concrete client types that are generated from *.proto files. O cliente gRPC concreto tem métodos que se convertem para o serviço gRPC no arquivo * * . proto* .The concrete gRPC client has methods that translate to the gRPC service in the *.proto file.

Um cliente gRPC é criado a partir de um canal.A gRPC client is created from a channel. Comece usando GrpcChannel.ForAddress para criar um canal e, em seguida, use o canal para criar um cliente 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);

Um canal representa uma conexão de vida útil longa para um serviço gRPC.A channel represents a long-lived connection to a gRPC service. Quando um canal é criado, ele é configurado com opções relacionadas à chamada de um serviço.When a channel is created, it is configured with options related to calling a service. Por exemplo, o HttpClient usado para fazer chamadas, o tamanho máximo de mensagens de envio e recebimento e o registro em log podem ser especificados GrpcChannelOptions e usados com o 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. Para obter uma lista completa de opções, consulte Opções de configuração do cliente.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

Configurar TLSConfigure TLS

Um cliente gRPC deve usar a mesma segurança de nível de conexão que o serviço chamado.A gRPC client must use the same connection-level security as the called service. o protocolo TLS do gRPC é configurado quando o canal gRPC é criado.gRPC client Transport Layer Security (TLS) is configured when the gRPC channel is created. Um cliente gRPC gera um erro ao chamar um serviço e a segurança no nível de conexão do canal e do serviço não correspondem.A gRPC client throws an error when it calls a service and the connection-level security of the channel and service don't match.

Para configurar um canal do gRPC para usar o TLS, verifique se o endereço do servidor começa com https .To configure a gRPC channel to use TLS, ensure the server address starts with https. Por exemplo, GrpcChannel.ForAddress("https://localhost:5001") usa o protocolo HTTPS.For example, GrpcChannel.ForAddress("https://localhost:5001") uses HTTPS protocol. O canal gRPC automaticamente negotates uma conexão protegida pelo TLS e usa uma conexão segura para fazer chamadas gRPC.The gRPC channel automatically negotates a connection secured by TLS and uses a secure connection to make gRPC calls.

Dica

o gRPC dá suporte à autenticação de certificado do cliente sobre TLS.gRPC supports client certificate authentication over TLS. Para obter informações sobre como configurar certificados de cliente com um canal do gRPC, consulte Autenticação e autorização no gRPC para ASP.NET Core .For information on configuring client certificates with a gRPC channel, see Autenticação e autorização no gRPC para ASP.NET Core.

Para chamar serviços gRPCs não seguros, verifique se o endereço do servidor começa com http .To call unsecured gRPC services, ensure the server address starts with http. Por exemplo, GrpcChannel.ForAddress("http://localhost:5000") usa o protocolo http.For example, GrpcChannel.ForAddress("http://localhost:5000") uses HTTP protocol. No .NET Core 3,1 ou posterior, é necessária configuração adicional para chamar serviços gRPCs inseguros com o cliente .net.In .NET Core 3.1 or later, additional configuration is required to call insecure gRPC services with the .NET client.

Desempenho do clienteClient performance

Desempenho e uso do canal e do cliente:Channel and client performance and usage:

  • A criação de um canal pode ser uma operação cara.Creating a channel can be an expensive operation. Reutilizar um canal para chamadas gRPC fornece benefícios de desempenho.Reusing a channel for gRPC calls provides performance benefits.
  • Os clientes do gRPC são criados com canais.gRPC clients are created with channels. Os clientes gRPC são objetos leves e não precisam ser armazenados em cache ou reutilizados.gRPC clients are lightweight objects and don't need to be cached or reused.
  • Vários clientes gRPC podem ser criados a partir de um canal, incluindo diferentes tipos de clientes.Multiple gRPC clients can be created from a channel, including different types of clients.
  • Um canal e clientes criados a partir do canal podem ser usados com segurança por vários threads.A channel and clients created from the channel can safely be used by multiple threads.
  • Clientes criados a partir do canal podem fazer várias chamadas simultâneas.Clients created from the channel can make multiple simultaneous calls.

GrpcChannel.ForAddressNão é a única opção para criar um cliente gRPC.GrpcChannel.ForAddress isn't the only option for creating a gRPC client. Se estiver chamando serviços gRPC de um aplicativo ASP.NET Core, considere a integração do gRPC Client Factory.If calling gRPC services from an ASP.NET Core app, consider gRPC client factory integration. a integração do gRPC com HttpClientFactory oferece uma alternativa centralizada para a criação de clientes do gRPC.gRPC integration with HttpClientFactory offers a centralized alternative to creating gRPC clients.

Observação

Não há suporte para a chamada de gRPC sobre HTTP/2 com Grpc.Net.Client atualmente no Xamarin.Calling gRPC over HTTP/2 with Grpc.Net.Client is currently not supported on Xamarin. Estamos trabalhando para melhorar o suporte a HTTP/2 em uma versão futura do Xamarin.We are working to improve HTTP/2 support in a future Xamarin release. Grpc. Core e Grpc-Web são alternativas viáveis que funcionam hoje.Grpc.Core and gRPC-Web are viable alternatives that work today.

Fazer chamadas gRPCMake gRPC calls

Uma chamada gRPC é iniciada chamando um método no cliente.A gRPC call is initiated by calling a method on the client. O cliente gRPC tratará da serialização de mensagens e abordará a chamada gRPC para o serviço correto.The gRPC client will handle message serialization and addressing the gRPC call to the correct service.

gRPC tem tipos diferentes de métodos.gRPC has different types of methods. Como o cliente é usado para fazer uma chamada gRPC depende do tipo de método chamado.How the client is used to make a gRPC call depends on the type of method called. Os tipos de método gRPC são:The gRPC method types are:

  • UnárioUnary
  • Transmissão de servidorServer streaming
  • Streaming de clienteClient streaming
  • Streaming bidirecionalBi-directional streaming

Chamada unárioUnary call

Uma chamada unário começa com o cliente enviando uma mensagem de solicitação.A unary call starts with the client sending a request message. Uma mensagem de resposta é retornada quando o serviço é concluído.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

Cada método de serviço unário no arquivo * * . proto* resultará em dois métodos .net no tipo de cliente concreto gRPC para chamar o método: um método assíncrono e um método de bloqueio.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. Por exemplo, GreeterClient há duas maneiras de chamar SayHello :For example, on GreeterClient there are two ways of calling SayHello:

  • GreeterClient.SayHelloAsync-chama o Greeter.SayHello serviço de forma assíncrona.GreeterClient.SayHelloAsync - calls Greeter.SayHello service asynchronously. Pode ser esperado.Can be awaited.
  • GreeterClient.SayHello-chama Greeter.SayHello serviço e bloqueia até a conclusão.GreeterClient.SayHello - calls Greeter.SayHello service and blocks until complete. Não use em código assíncrono.Don't use in asynchronous code.

Chamada de streaming de servidorServer streaming call

Uma chamada de transmissão de servidor inicia com o cliente enviando uma mensagem de solicitação.A server streaming call starts with the client sending a request message. ResponseStream.MoveNext()lê mensagens transmitidas do serviço.ResponseStream.MoveNext() reads messages streamed from the service. A chamada de streaming de servidor é concluída quando ResponseStream.MoveNext() retorna 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
}

Ao usar o C# 8 ou posterior, a await foreach sintaxe pode ser usada para ler mensagens.When using C# 8 or later, the await foreach syntax can be used to read messages. O IAsyncStreamReader<T>.ReadAllAsync() método de extensão lê todas as mensagens do fluxo de resposta: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
}

Chamada de streaming de clienteClient streaming call

Uma chamada de streaming de cliente inicia sem que o cliente envie uma mensagem.A client streaming call starts without the client sending a message. O cliente pode optar por enviar mensagens com RequestStream.WriteAsync .The client can choose to send messages with RequestStream.WriteAsync. Quando o cliente terminar de enviar mensagens, RequestStream.CompleteAsync deverá ser chamado para notificar o serviço.When the client has finished sending messages, RequestStream.CompleteAsync should be called to notify the service. A chamada é concluída quando o serviço retorna uma mensagem de resposta.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

Chamada de streaming bidirecionalBi-directional streaming call

Uma chamada de streaming bidirecional é iniciada sem que o cliente envie uma mensagem.A bi-directional streaming call starts without the client sending a message. O cliente pode optar por enviar mensagens com RequestStream.WriteAsync .The client can choose to send messages with RequestStream.WriteAsync. As mensagens transmitidas do serviço são acessíveis com o ResponseStream.MoveNext() ou o ResponseStream.ReadAllAsync() .Messages streamed from the service are accessible with ResponseStream.MoveNext() or ResponseStream.ReadAllAsync(). A chamada de streaming bidirecional é concluída quando o ResponseStream não tem mais mensagens.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;

Durante uma chamada de streaming bidirecional, o cliente e o serviço podem enviar mensagens entre si a qualquer momento.During a bi-directional streaming call, the client and service can send messages to each other at any time. A melhor lógica de cliente para interagir com uma chamada bidirecional varia dependendo da lógica do serviço.The best client logic for interacting with a bi-directional call varies depending upon the service logic.

Acesse os trailers gRPCAccess gRPC trailers

chamadas gRPC podem retornar gRPCs.gRPC calls may return gRPC trailers. os trailers de gRPC são usados para fornecer metadados de nome/valor sobre uma chamada.gRPC trailers are used to provide name/value metadata about a call. Os trailers fornecem funcionalidade semelhante aos cabeçalhos HTTP, mas são recebidos no final da chamada.Trailers provide similar functionality to HTTP headers, but are received at the end of the call.

os trailers de gRPC são acessíveis usando GetTrailers() , que retorna uma coleção de metadados.gRPC trailers are accessible using GetTrailers(), which returns a collection of metadata. Os trailers são retornados após a conclusão da resposta, portanto, você deve aguardar todas as mensagens de resposta antes de acessar os trailers.Trailers are returned after the response is complete, therefore, you must await all response messages before accessing the trailers.

Chamadas unários e de streaming de cliente devem aguardar ResponseAsync antes de chamar 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");

As chamadas de streaming de servidor e bidirecional devem terminar de aguardar o fluxo de resposta antes de chamar 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");

os trailers de gRPC também podem ser acessados do RpcException .gRPC trailers are also accessible from RpcException. Um serviço pode retornar os trailers com um status de gRPC não OK.A service may return trailers together with a non-OK gRPC status. Nessa situação, os trailers são recuperados da exceção gerada pelo cliente 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");
}

Recursos adicionaisAdditional resources