Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Note
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 10 deste artigo.
Warning
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e do .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.
Este documento discute problemas comumente encontrados ao desenvolver aplicativos gRPC no .NET.
Incompatibilidade entre a configuração SSL/TLS do cliente e do serviço
O modelo gRPC e os exemplos usam Transport Layer Security (TLS) para proteger serviços gRPC por padrão. Os clientes gRPC precisam usar uma conexão segura para chamar serviços gRPC seguros com êxito.
Você pode verificar se o serviço gRPC ASP.NET Core está usando TLS nos logs gravados na inicialização do aplicativo. O serviço estará a escutar num endpoint HTTPS.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
O cliente .NET deve usar https no endereço do servidor para fazer chamadas com uma conexão segura:
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
Todas as implementações de cliente gRPC suportam TLS. Os clientes gRPC de outros idiomas normalmente exigem o canal configurado com SslCredentials.
SslCredentials Especifica o certificado que o cliente usará e ele deve ser usado em vez de credenciais inseguras. Para obter exemplos de configuração das diferentes implementações de cliente gRPC para usar TLS, consulte Autenticação gRPC.
Chamar um serviço gRPC com um certificado não confiável ou inválido
O cliente gRPC do .NET requer que o serviço tenha um certificado confiável. A seguinte mensagem de erro é retornada ao chamar um serviço gRPC sem um certificado confiável:
Exceção não tratada. System.Net.Http.HttpRequestException: A conexão SSL não pôde ser estabelecida, consulte exceção interna. >--- System.Security.Authentication.AuthenticationException: O certificado remoto é inválido de acordo com o procedimento de validação.
Você poderá ver esse erro se estiver testando seu aplicativo localmente e o certificado de desenvolvimento HTTPS ASP.NET Core não for confiável. Para obter instruções para corrigir esse problema, consulte Confiar no certificado de desenvolvimento HTTPS do ASP.NET Core no Windows e macOS.
Se você estiver chamando um serviço gRPC em outra máquina e não puder confiar no certificado, o cliente gRPC poderá ser configurado para ignorar o certificado inválido. O código a seguir usa HttpClientHandler.ServerCertificateCustomValidationCallback para permitir chamadas sem um certificado confiável:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
A fábrica do cliente gRPC permite chamadas sem um certificado confiável. Use o ConfigurePrimaryHttpMessageHandler método de extensão para configurar o manipulador no cliente.
var services = new ServiceCollection();
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Warning
Os certificados não confiáveis só devem ser usados durante o desenvolvimento do aplicativo. Os aplicativos de produção devem sempre usar certificados válidos.
Chamar serviços gRPC inseguros com cliente .NET
O cliente gRPC .NET pode chamar serviços gRPC inseguros especificando http o endereço do servidor. Por exemplo, GrpcChannel.ForAddress("http://localhost:5000").
Há alguns requisitos adicionais para chamar serviços gRPC inseguros, dependendo da versão .NET que um aplicativo está usando:
- O .NET 5 ou posterior requer Grpc.Net.Client versão 2.32.0 ou posterior.
- O .NET Core 3.x requer configuração adicional. A aplicação deve definir o
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupportinterruptor paratrue. Para obter mais informações , consulte Asp.Net Core 3.x: Chamar serviços gRPC inseguros com o cliente .NET:
Important
Os serviços gRPC inseguros devem ser hospedados em uma porta somente HTTP/2. Para obter mais informações, consulte ASP.NET negociação de protocolo principal.
Não é possível iniciar ASP.NET aplicativo gRPC Core no macOS
Kestrel não suporta HTTP/2 com TLS no macOS antes do .NET 8. O modelo e os exemplos do ASP.NET Core gRPC usam TLS por padrão. Você verá a seguinte mensagem de erro ao tentar iniciar o servidor gRPC:
Não é possível ligar à interface de retorno IPv4 https://localhost:5001: 'HTTP/2 sobre TLS não é suportado no macOS devido à ausência de suporte ALPN.'.
Para contornar esse problema no .NET 7 ou anterior, configure Kestrel e o cliente gRPC para usar HTTP/2 sem TLS. Você só deve fazer isso durante o desenvolvimento. Não usar TLS resultará no envio de mensagens gRPC sem criptografia. Para obter mais informações, consulte ASP.NET Core no .NET 7: Não é possível iniciar ASP.NET aplicativo gRPC Core no macOS.
Os ativos gRPC C# não são código gerado a partir de .proto arquivos
A geração de código gRPC de clientes concretos e classes base de serviço requer que os ficheiros protobuf e as ferramentas sejam referenciados a partir de um projeto. Deve incluir:
-
.protoarquivos que pretende usar no grupo de itens<Protobuf>. Os arquivos importados.protodevem ser referenciados pelo projeto. - Referência de pacote para o pacote de ferramentas gRPC Grpc.Tools.
Para obter mais informações sobre como gerar ativos gRPC C#, consulte Serviços gRPC com C#.
Um aplicativo Web ASP.NET Core que hospeda serviços gRPC só precisa da classe base de serviço gerada:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Um aplicativo cliente gRPC que faz chamadas gRPC só precisa do cliente concreto gerado:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
Projetos WPF não são capazes de gerar ativos gRPC C# de arquivos .proto.
Os projetos WPF têm um problema conhecido que impede a geração de código gRPC de funcionar corretamente. Quaisquer tipos de gRPC gerados num projeto WPF por referência aos Grpc.Tools e .proto arquivos criarão erros de compilação quando usados:
erro CS0246: O tipo ou nome de namespace 'MyGrpcServices' não pôde ser encontrado (está a faltar uma diretiva using ou uma referência de assembly?)
Você pode solucionar esse problema da seguinte forma:
- Crie um novo projeto de biblioteca de classes .NET.
- No novo projeto, adicione referências para habilitar a geração de código C# a partir de
.protoarquivos:- Adicione as seguintes referências de pacote:
- Adicione
.protoarquivos ao grupo de<Protobuf>itens.
- No aplicativo WPF, adicione uma referência ao novo projeto.
A aplicação WPF pode usar os tipos gerados pelo gRPC do novo projeto de biblioteca de classes.
Chamando serviços gRPC hospedados em um subdiretório
Warning
Muitas ferramentas gRPC de terceiros não suportam serviços hospedados em subdiretórios. Considere encontrar uma maneira de hospedar gRPC como o diretório raiz.
O componente de caminho do endereço de um canal gRPC é ignorado ao fazer chamadas gRPC. Por exemplo, GrpcChannel.ForAddress("https://localhost:5001/ignored_path") não usará ignored_path ao rotear chamadas gRPC para o serviço.
O caminho de endereço é ignorado porque o gRPC tem uma estrutura de endereço padronizada e prescritiva. Um endereço gRPC combina os nomes de pacote, serviço e método: https://localhost:5001/PackageName.ServiceName/MethodName.
Há alguns cenários em que um aplicativo precisa incluir um caminho com chamadas gRPC. Por exemplo, quando um aplicativo gRPC ASP.NET Core é hospedado em um diretório do IIS e o diretório precisa ser incluído na solicitação. Quando um caminho é necessário, ele pode ser adicionado à chamada gRPC usando o personalizado SubdirectoryHandler especificado abaixo:
public class SubdirectoryHandler : DelegatingHandler
{
private readonly string _subdirectory;
public SubdirectoryHandler(HttpMessageHandler innerHandler, string subdirectory)
: base(innerHandler)
{
_subdirectory = subdirectory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler é usado quando o canal gRPC é criado.
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/MyApp");
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
O código anterior:
- Cria um
SubdirectoryHandlercom o caminho/MyApp. - Configura um canal para usar
SubdirectoryHandler. - Chama o serviço gRPC com
SayHelloAsync. A chamada gRPC é enviada parahttps://localhost:5001/MyApp/greet.Greeter/SayHello.
Como alternativa, uma fábrica cliente pode ser configurada com SubdirectoryHandler usando AddHttpMessageHandler.
Configurar o cliente gRPC para usar HTTP/3
O cliente gRPC .NET suporta HTTP/3 com .NET 6 ou posterior. Se o servidor enviar um cabeçalho de alt-svc resposta para o cliente que indique que o servidor suporta HTTP/3, o cliente atualizará automaticamente sua conexão para HTTP/3. Para obter mais informações, consulte Usar HTTP/3 com o servidor Web ASP.NET CoreKestrel.
A DelegatingHandler pode ser usado para forçar um cliente gRPC a usar HTTP/3. Forçar HTTP/3 evita a sobrecarga de atualizar a solicitação. Força HTTP/3 com código semelhante ao seguinte:
public class Http3Handler : DelegatingHandler
{
public Http3Handler() { }
public Http3Handler(HttpMessageHandler innerHandler) : base(innerHandler) { }
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Version = HttpVersion.Version30;
request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;
return base.SendAsync(request, cancellationToken);
}
}
Http3Handler é usado quando o canal gRPC é criado. O código a seguir cria um canal configurado para usar Http3Handler.
var handler = new Http3Handler(new HttpClientHandler());
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });
Como alternativa, uma fábrica cliente pode ser configurada com Http3Handler usando AddHttpMessageHandler.
Construindo gRPC no Alpine Linux
O Grpc.Tools pacote gera tipos .NET a partir de .proto ficheiros usando um binário nativo chamado protoc. Etapas adicionais são necessárias para criar aplicativos gRPC em plataformas que não são suportadas pelos binários nativos no Grpc.Tools, como o Alpine Linux.
Gere código com antecedência
Uma solução é gerar código com antecedência.
- Mova
.protoarquivos e a referência doGrpc.Toolspacote para um novo projeto. - Publique o projeto como um pacote NuGet e carregue-o em um feed do NuGet.
- Atualize o aplicativo para fazer referência ao pacote NuGet.
Com as etapas anteriores, a aplicação já não precisa de Grpc.Tools para compilar porque o código é gerado com antecedência.
Personalizar Grpc.Tools binários nativos
Grpc.Tools suporta o uso de binários nativos personalizados. Esse recurso permite que as ferramentas gRPC sejam executadas em ambientes que seus binários nativos agrupados não suportam.
Adquira ou desenvolva binários nativos para protoc e grpc_csharp_plugin e configure Grpc.Tools para utilizá-los. Configure binários nativos definindo as seguintes variáveis de ambiente:
-
PROTOBUF_PROTOC- Caminho completo para o compilador de buffers de protocolo -
GRPC_PROTOC_PLUGIN- Caminho completo para o grpc_csharp_plugin
Para o Alpine Linux, existem pacotes fornecidos pela comunidade para o compilador de buffers de protocolo e plugins gRPC em https://pkgs.alpinelinux.org/.
# Build or install the binaries for your architecture.
# For Alpine Linux, the grpc-plugins package can be used.
# See https://pkgs.alpinelinux.org/package/edge/community/x86_64/grpc-plugins
apk add grpc-plugins # Alpine Linux specific package installer
# Set environment variables for the built/installed protoc
# and grpc_csharp_plugin binaries
export PROTOBUF_PROTOC=/usr/bin/protoc
export GRPC_PROTOC_PLUGIN=/usr/bin/grpc_csharp_plugin
# When dotnet build runs, the Grpc.Tools NuGet package
# uses the binaries pointed to by the environment variables.
dotnet build
Para obter mais informações sobre como usar Grpc.Tools com arquiteturas sem suporte, consulte a documentação de integração de compilação gRPC.
Tempo limite de chamada gRPC a partir de HttpClient.Timeout
HttpClient é configurado com um tempo limite de 100 segundos por padrão. Se um GrpcChannel estiver configurado para usar um HttpClient, as chamadas de transmissão gRPC de longa duração serão canceladas se não forem concluídas dentro do limite de tempo.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Há algumas maneiras de corrigir esse erro. A primeira é configurar HttpClient.Timeout para um valor maior. Timeout.InfiniteTimeSpan Desativa o tempo limite:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(handler) { Timeout = Timeout.InfiniteTimeSpan };
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Greeter.GreeterClient(channel);
Como alternativa, evite criar HttpClient e definir GrpcChannel.HttpHandler :
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
Este documento discute problemas comumente encontrados ao desenvolver aplicativos gRPC no .NET.
Incompatibilidade entre a configuração SSL/TLS do cliente e do serviço
O modelo gRPC e os exemplos usam Transport Layer Security (TLS) para proteger serviços gRPC por padrão. Os clientes gRPC precisam usar uma conexão segura para chamar serviços gRPC seguros com êxito.
Você pode verificar se o serviço gRPC ASP.NET Core está usando TLS nos logs gravados na inicialização do aplicativo. O serviço estará a escutar num endpoint HTTPS.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
O cliente .NET deve usar https no endereço do servidor para fazer chamadas com uma conexão segura:
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greet.GreeterClient(channel);
}
Todas as implementações de cliente gRPC suportam TLS. Os clientes gRPC de outros idiomas normalmente exigem o canal configurado com SslCredentials.
SslCredentials Especifica o certificado que o cliente usará e ele deve ser usado em vez de credenciais inseguras. Para obter exemplos de configuração das diferentes implementações de cliente gRPC para usar TLS, consulte Autenticação gRPC.
Chamar um serviço gRPC com um certificado não confiável ou inválido
O cliente gRPC do .NET requer que o serviço tenha um certificado confiável. A seguinte mensagem de erro é retornada ao chamar um serviço gRPC sem um certificado confiável:
Exceção não tratada. System.Net.Http.HttpRequestException: A conexão SSL não pôde ser estabelecida, consulte exceção interna. >--- System.Security.Authentication.AuthenticationException: O certificado remoto é inválido de acordo com o procedimento de validação.
Você poderá ver esse erro se estiver testando seu aplicativo localmente e o certificado de desenvolvimento HTTPS ASP.NET Core não for confiável. Para obter instruções para corrigir esse problema, consulte Confiar no certificado de desenvolvimento HTTPS do ASP.NET Core no Windows e macOS.
Se você estiver chamando um serviço gRPC em outra máquina e não puder confiar no certificado, o cliente gRPC poderá ser configurado para ignorar o certificado inválido. O código a seguir usa HttpClientHandler.ServerCertificateCustomValidationCallback para permitir chamadas sem um certificado confiável:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
A fábrica do cliente gRPC permite chamadas sem um certificado confiável. Use o ConfigurePrimaryHttpMessageHandler método de extensão para configurar o manipulador no cliente.
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Warning
Os certificados não confiáveis só devem ser usados durante o desenvolvimento do aplicativo. Os aplicativos de produção devem sempre usar certificados válidos.
Chamar serviços gRPC inseguros com cliente .NET
O cliente gRPC .NET pode chamar serviços gRPC inseguros especificando http o endereço do servidor. Por exemplo, GrpcChannel.ForAddress("http://localhost:5000").
Há alguns requisitos adicionais para chamar serviços gRPC inseguros, dependendo da versão .NET que um aplicativo está usando:
O .NET 5 ou posterior requer Grpc.Net.Client versão 2.32.0 ou posterior.
O .NET Core 3.x requer configuração adicional. A aplicação deve definir o interruptor
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupportparatrue:// This switch must be set before creating the GrpcChannel/HttpClient. AppContext.SetSwitch( "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); // The port number(5000) must match the port of the gRPC server. var channel = GrpcChannel.ForAddress("http://localhost:5000"); var client = new Greet.GreeterClient(channel);
A opção só é necessária para o System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport .NET Core 3.x. Ele não faz nada no .NET 5 e não é necessário.
Important
Os serviços gRPC inseguros devem ser hospedados em uma porta somente HTTP/2. Para obter mais informações, consulte ASP.NET negociação de protocolo principal.
Não é possível iniciar ASP.NET aplicativo gRPC Core no macOS
Kestrel não suporta HTTP/2 com TLS no macOS antes do .NET 8. O modelo e os exemplos do ASP.NET Core gRPC usam TLS por padrão. Você verá a seguinte mensagem de erro ao tentar iniciar o servidor gRPC:
Não é possível ligar à interface de retorno IPv4 https://localhost:5001: 'HTTP/2 sobre TLS não é suportado no macOS devido à ausência de suporte ALPN.'.
Para contornar esse problema no .NET 7 ou anterior, configure Kestrel e o cliente gRPC para usar HTTP/2 sem TLS. Você só deve fazer isso durante o desenvolvimento. Não usar TLS resultará no envio de mensagens gRPC sem criptografia.
Kestrel deve configurar um ponto de extremidade HTTP/2 sem TLS em Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(<5287>, o => o.Protocols =
HttpProtocols.Http2);
});
- No código anterior, substitua o número da porta localhost
5287pelo número da portaHTTP(nãoHTTPS) especificado no projeto de serviço gRPCProperties/launchSettings.json.
Quando um ponto de extremidade HTTP/2 é configurado sem TLS, ListenOptions.Protocols do ponto de extremidade deve ser definido como HttpProtocols.Http2.
HttpProtocols.Http1AndHttp2 não pode ser usado porque o TLS é necessário para negociar HTTP/2. Sem TLS, todas as ligações com o ponto de extremidade revertem para o padrão HTTP/1.1, e as chamadas gRPC falham.
O cliente gRPC também deve ser configurado para não usar TLS. Para obter mais informações, consulte Chamar serviços gRPC inseguros com cliente .NET.
Warning
HTTP/2 sem TLS só deve ser usado durante o desenvolvimento do aplicativo. Os aplicativos de produção devem sempre usar segurança de transporte. Para obter mais informações, consulte Considerações de segurança no gRPC para ASP.NET Core.
Os ativos gRPC C# não são código gerado a partir de .proto arquivos
A geração de código gRPC de clientes concretos e classes base de serviço requer que os ficheiros protobuf e as ferramentas sejam referenciados a partir de um projeto. Deve incluir:
-
.protoarquivos que pretende usar no grupo de itens<Protobuf>. Os arquivos importados.protodevem ser referenciados pelo projeto. - Referência de pacote para o pacote de ferramentas gRPC Grpc.Tools.
Para obter mais informações sobre como gerar ativos gRPC C#, consulte Serviços gRPC com C#.
Um aplicativo Web ASP.NET Core que hospeda serviços gRPC só precisa da classe base de serviço gerada:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Um aplicativo cliente gRPC que faz chamadas gRPC só precisa do cliente concreto gerado:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
Projetos WPF não são capazes de gerar ativos gRPC C# de arquivos .proto.
Os projetos WPF têm um problema conhecido que impede a geração de código gRPC de funcionar corretamente. Quaisquer tipos de gRPC gerados num projeto WPF por referência aos Grpc.Tools e .proto arquivos criarão erros de compilação quando usados:
erro CS0246: O tipo ou nome de namespace 'MyGrpcServices' não pôde ser encontrado (está a faltar uma diretiva using ou uma referência de assembly?)
Você pode solucionar esse problema da seguinte forma:
- Crie um novo projeto de biblioteca de classes .NET.
- No novo projeto, adicione referências para habilitar a geração de código C# a partir de
.protoarquivos:- Adicione as seguintes referências de pacote:
- Adicione
.protoarquivos ao grupo de<Protobuf>itens.
- No aplicativo WPF, adicione uma referência ao novo projeto.
A aplicação WPF pode usar os tipos gerados pelo gRPC do novo projeto de biblioteca de classes.
Chamando serviços gRPC hospedados em um subdiretório
Warning
Muitas ferramentas gRPC de terceiros não suportam serviços hospedados em subdiretórios. Considere encontrar uma maneira de hospedar gRPC como o diretório raiz.
O componente de caminho do endereço de um canal gRPC é ignorado ao fazer chamadas gRPC. Por exemplo, GrpcChannel.ForAddress("https://localhost:5001/ignored_path") não usará ignored_path ao rotear chamadas gRPC para o serviço.
O caminho de endereço é ignorado porque o gRPC tem uma estrutura de endereço padronizada e prescritiva. Um endereço gRPC combina os nomes de pacote, serviço e método: https://localhost:5001/PackageName.ServiceName/MethodName.
Há alguns cenários em que um aplicativo precisa incluir um caminho com chamadas gRPC. Por exemplo, quando um aplicativo gRPC ASP.NET Core é hospedado em um diretório do IIS e o diretório precisa ser incluído na solicitação. Quando um caminho é necessário, ele pode ser adicionado à chamada gRPC usando o personalizado SubdirectoryHandler especificado abaixo:
/// <summary>
/// A delegating handler that adds a subdirectory to the URI of gRPC requests.
/// </summary>
public class SubdirectoryHandler : DelegatingHandler
{
private readonly string _subdirectory;
public SubdirectoryHandler(HttpMessageHandler innerHandler, string subdirectory)
: base(innerHandler)
{
_subdirectory = subdirectory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler é usado quando o canal gRPC é criado.
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/MyApp");
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
O código anterior:
- Cria um
SubdirectoryHandlercom o caminho/MyApp. - Configura um canal para usar
SubdirectoryHandler. - Chama o serviço gRPC com
SayHelloAsync. A chamada gRPC é enviada parahttps://localhost:5001/MyApp/greet.Greeter/SayHello.
Como alternativa, uma fábrica cliente pode ser configurada com SubdirectoryHandler usando AddHttpMessageHandler.
Configurar o cliente gRPC para usar HTTP/3
O cliente gRPC .NET suporta HTTP/3 com .NET 6 ou posterior. Se o servidor enviar um cabeçalho de alt-svc resposta para o cliente que indique que o servidor suporta HTTP/3, o cliente atualizará automaticamente sua conexão para HTTP/3. Para obter informações sobre como habilitar HTTP/3 no servidor, consulte Usar HTTP/3 com o servidor Web ASP.NET CoreKestrel.
O suporte a HTTP/3 no .NET 8 está habilitado por padrão. O suporte a HTTP/3 no .NET 6 e .NET 7 precisa ser habilitado por meio de um sinalizador de configuração no arquivo de projeto:
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Net.SocketsHttpHandler.Http3Support" Value="true" />
</ItemGroup>
System.Net.SocketsHttpHandler.Http3Support também pode ser definido usando AppContext.SetSwitch.
A DelegatingHandler pode ser usado para forçar um cliente gRPC a usar HTTP/3. Forçar HTTP/3 evita a sobrecarga de atualizar a solicitação. Força HTTP/3 com código semelhante ao seguinte:
/// <summary>
/// A delegating handler that changes the request HTTP version to HTTP/3.
/// </summary>
public class Http3Handler : DelegatingHandler
{
public Http3Handler() { }
public Http3Handler(HttpMessageHandler innerHandler) : base(innerHandler) { }
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Version = HttpVersion.Version30;
request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;
return base.SendAsync(request, cancellationToken);
}
}
Http3Handler é usado quando o canal gRPC é criado. O código a seguir cria um canal configurado para usar Http3Handler.
var handler = new Http3Handler(new HttpClientHandler());
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
Como alternativa, uma fábrica cliente pode ser configurada com Http3Handler usando AddHttpMessageHandler.
Construindo gRPC no Alpine Linux
O Grpc.Tools pacote gera tipos .NET a partir de .proto ficheiros usando um binário nativo chamado protoc. Etapas adicionais são necessárias para criar aplicativos gRPC em plataformas que não são suportadas pelos binários nativos no Grpc.Tools, como o Alpine Linux.
Gere código com antecedência
Uma solução é gerar código com antecedência.
- Mova
.protoarquivos e a referência doGrpc.Toolspacote para um novo projeto. - Publique o projeto como um pacote NuGet e carregue-o em um feed do NuGet.
- Atualize o aplicativo para fazer referência ao pacote NuGet.
Com as etapas anteriores, a aplicação já não precisa de Grpc.Tools para compilar porque o código é gerado com antecedência.
Personalizar Grpc.Tools binários nativos
Grpc.Tools suporta o uso de binários nativos personalizados. Esse recurso permite que as ferramentas gRPC sejam executadas em ambientes que seus binários nativos agrupados não suportam.
Adquira ou desenvolva binários nativos para protoc e grpc_csharp_plugin e configure Grpc.Tools para utilizá-los. Configure binários nativos definindo as seguintes variáveis de ambiente:
-
PROTOBUF_PROTOC- Caminho completo para o compilador de buffers de protocolo -
GRPC_PROTOC_PLUGIN- Caminho completo para o grpc_csharp_plugin
Para o Alpine Linux, existem pacotes fornecidos pela comunidade para o compilador de buffers de protocolo e plugins gRPC em https://pkgs.alpinelinux.org/.
# Build or install the binaries for your architecture.
# For Alpine Linux, the grpc-plugins package can be used.
# See https://pkgs.alpinelinux.org/package/edge/community/x86_64/grpc-plugins
apk add grpc-plugins # Alpine Linux specific package installer
# Set environment variables for the built/installed protoc
# and grpc_csharp_plugin binaries
export PROTOBUF_PROTOC=/usr/bin/protoc
export GRPC_PROTOC_PLUGIN=/usr/bin/grpc_csharp_plugin
# When dotnet build runs, the Grpc.Tools NuGet package
# uses the binaries pointed to by the environment variables.
dotnet build
Para obter mais informações sobre como usar Grpc.Tools com arquiteturas sem suporte, consulte a documentação de integração de compilação gRPC.
Tempo limite de chamada gRPC a partir de HttpClient.Timeout
HttpClient é configurado com um tempo limite de 100 segundos por padrão. Se um GrpcChannel estiver configurado para usar um HttpClient, as chamadas de transmissão gRPC de longa duração serão canceladas se não forem concluídas dentro do limite de tempo.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Há algumas maneiras de corrigir esse erro. A primeira é configurar HttpClient.Timeout para um valor maior. Timeout.InfiniteTimeSpan Desativa o tempo limite:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(handler) { Timeout = Timeout.InfiniteTimeSpan };
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Greeter.GreeterClient(channel);
Como alternativa, evite criar HttpClient e definir GrpcChannel.HttpHandler :
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
Este documento discute problemas comumente encontrados ao desenvolver aplicativos gRPC no .NET.
Incompatibilidade entre a configuração SSL/TLS do cliente e do serviço
O modelo gRPC e os exemplos usam Transport Layer Security (TLS) para proteger serviços gRPC por padrão. Os clientes gRPC precisam usar uma conexão segura para chamar serviços gRPC seguros com êxito.
Você pode verificar se o serviço gRPC ASP.NET Core está usando TLS nos logs gravados na inicialização do aplicativo. O serviço estará a escutar num endpoint HTTPS.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
O cliente .NET deve usar https no endereço do servidor para fazer chamadas com uma conexão segura:
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greet.GreeterClient(channel);
}
Todas as implementações de cliente gRPC suportam TLS. Os clientes gRPC de outros idiomas normalmente exigem o canal configurado com SslCredentials.
SslCredentials Especifica o certificado que o cliente usará e ele deve ser usado em vez de credenciais inseguras. Para obter exemplos de configuração das diferentes implementações de cliente gRPC para usar TLS, consulte Autenticação gRPC.
Chamar um serviço gRPC com um certificado não confiável ou inválido
O cliente gRPC do .NET requer que o serviço tenha um certificado confiável. A seguinte mensagem de erro é retornada ao chamar um serviço gRPC sem um certificado confiável:
Exceção não tratada. System.Net.Http.HttpRequestException: A conexão SSL não pôde ser estabelecida, consulte exceção interna. >--- System.Security.Authentication.AuthenticationException: O certificado remoto é inválido de acordo com o procedimento de validação.
Você poderá ver esse erro se estiver testando seu aplicativo localmente e o certificado de desenvolvimento HTTPS ASP.NET Core não for confiável. Para obter instruções para corrigir esse problema, consulte Confiar no certificado de desenvolvimento HTTPS do ASP.NET Core no Windows e macOS.
Se você estiver chamando um serviço gRPC em outra máquina e não puder confiar no certificado, o cliente gRPC poderá ser configurado para ignorar o certificado inválido. O código a seguir usa HttpClientHandler.ServerCertificateCustomValidationCallback para permitir chamadas sem um certificado confiável:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
A fábrica do cliente gRPC permite chamadas sem um certificado confiável. Use o ConfigurePrimaryHttpMessageHandler método de extensão para configurar o manipulador no cliente.
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Warning
Os certificados não confiáveis só devem ser usados durante o desenvolvimento do aplicativo. Os aplicativos de produção devem sempre usar certificados válidos.
Chamar serviços gRPC inseguros com cliente .NET
O cliente gRPC .NET pode chamar serviços gRPC inseguros especificando http o endereço do servidor. Por exemplo, GrpcChannel.ForAddress("http://localhost:5000").
Há alguns requisitos adicionais para chamar serviços gRPC inseguros, dependendo da versão .NET que um aplicativo está usando:
O .NET 5 ou posterior requer Grpc.Net.Client versão 2.32.0 ou posterior.
O .NET Core 3.x requer configuração adicional. A aplicação deve definir o interruptor
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupportparatrue:// This switch must be set before creating the GrpcChannel/HttpClient. AppContext.SetSwitch( "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); // The port number(5000) must match the port of the gRPC server. var channel = GrpcChannel.ForAddress("http://localhost:5000"); var client = new Greet.GreeterClient(channel);
A opção só é necessária para o System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport .NET Core 3.x. Ele não faz nada no .NET 5 e não é necessário.
Important
Os serviços gRPC inseguros devem ser hospedados em uma porta somente HTTP/2. Para obter mais informações, consulte ASP.NET negociação de protocolo principal.
Não é possível iniciar ASP.NET aplicativo gRPC Core no macOS
Kestrel não suporta HTTP/2 com TLS no macOS antes do .NET 8. O modelo e os exemplos do ASP.NET Core gRPC usam TLS por padrão. Você verá a seguinte mensagem de erro ao tentar iniciar o servidor gRPC:
Não é possível ligar à interface de retorno IPv4 https://localhost:5001: 'HTTP/2 sobre TLS não é suportado no macOS devido à ausência de suporte ALPN.'.
Para contornar esse problema no .NET 7 ou anterior, configure Kestrel e o cliente gRPC para usar HTTP/2 sem TLS. Você só deve fazer isso durante o desenvolvimento. Não usar TLS resultará no envio de mensagens gRPC sem criptografia.
Kestrel deve configurar um ponto de extremidade HTTP/2 sem TLS em Program.cs:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(5000, o => o.Protocols =
HttpProtocols.Http2);
});
webBuilder.UseStartup<Startup>();
});
Quando um ponto de extremidade HTTP/2 é configurado sem TLS, ListenOptions.Protocols do ponto de extremidade deve ser definido como HttpProtocols.Http2.
HttpProtocols.Http1AndHttp2 não pode ser usado porque o TLS é necessário para negociar HTTP/2. Sem TLS, todas as ligações com o ponto de extremidade revertem para o padrão HTTP/1.1, e as chamadas gRPC falham.
O cliente gRPC também deve ser configurado para não usar TLS. Para obter mais informações, consulte Chamar serviços gRPC inseguros com cliente .NET.
Warning
HTTP/2 sem TLS só deve ser usado durante o desenvolvimento do aplicativo. Os aplicativos de produção devem sempre usar segurança de transporte. Para obter mais informações, consulte Considerações de segurança no gRPC para ASP.NET Core.
Os ativos gRPC C# não são código gerado a partir de .proto arquivos
A geração de código gRPC de clientes concretos e classes base de serviço requer que os ficheiros protobuf e as ferramentas sejam referenciados a partir de um projeto. Deve incluir:
-
.protoarquivos que pretende usar no grupo de itens<Protobuf>. Os arquivos importados.protodevem ser referenciados pelo projeto. - Referência de pacote para o pacote de ferramentas gRPC Grpc.Tools.
Para obter mais informações sobre como gerar ativos gRPC C#, consulte Serviços gRPC com C#.
Um aplicativo Web ASP.NET Core que hospeda serviços gRPC só precisa da classe base de serviço gerada:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Um aplicativo cliente gRPC que faz chamadas gRPC só precisa do cliente concreto gerado:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
Projetos WPF não são capazes de gerar ativos gRPC C# de arquivos .proto.
Os projetos WPF têm um problema conhecido que impede a geração de código gRPC de funcionar corretamente. Quaisquer tipos de gRPC gerados num projeto WPF por referência aos Grpc.Tools e .proto arquivos criarão erros de compilação quando usados:
erro CS0246: O tipo ou nome de namespace 'MyGrpcServices' não pôde ser encontrado (está a faltar uma diretiva using ou uma referência de assembly?)
Você pode solucionar esse problema da seguinte forma:
- Crie um novo projeto de biblioteca de classes .NET.
- No novo projeto, adicione referências para habilitar a geração de código C# a partir de
.protoarquivos:- Adicione as seguintes referências de pacote:
- Adicione
.protoarquivos ao grupo de<Protobuf>itens.
- No aplicativo WPF, adicione uma referência ao novo projeto.
A aplicação WPF pode usar os tipos gerados pelo gRPC do novo projeto de biblioteca de classes.
Chamando serviços gRPC hospedados em um subdiretório
Warning
Muitas ferramentas gRPC de terceiros não suportam serviços hospedados em subdiretórios. Considere encontrar uma maneira de hospedar gRPC como o diretório raiz.
O componente de caminho do endereço de um canal gRPC é ignorado ao fazer chamadas gRPC. Por exemplo, GrpcChannel.ForAddress("https://localhost:5001/ignored_path") não usará ignored_path ao rotear chamadas gRPC para o serviço.
O caminho de endereço é ignorado porque o gRPC tem uma estrutura de endereço padronizada e prescritiva. Um endereço gRPC combina os nomes de pacote, serviço e método: https://localhost:5001/PackageName.ServiceName/MethodName.
Há alguns cenários em que um aplicativo precisa incluir um caminho com chamadas gRPC. Por exemplo, quando um aplicativo gRPC ASP.NET Core é hospedado em um diretório do IIS e o diretório precisa ser incluído na solicitação. Quando um caminho é necessário, ele pode ser adicionado à chamada gRPC usando o personalizado SubdirectoryHandler especificado abaixo:
/// <summary>
/// A delegating handler that adds a subdirectory to the URI of gRPC requests.
/// </summary>
public class SubdirectoryHandler : DelegatingHandler
{
private readonly string _subdirectory;
public SubdirectoryHandler(HttpMessageHandler innerHandler, string subdirectory)
: base(innerHandler)
{
_subdirectory = subdirectory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler é usado quando o canal gRPC é criado.
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/MyApp");
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
O código anterior:
- Cria um
SubdirectoryHandlercom o caminho/MyApp. - Configura um canal para usar
SubdirectoryHandler. - Chama o serviço gRPC com
SayHelloAsync. A chamada gRPC é enviada parahttps://localhost:5001/MyApp/greet.Greeter/SayHello.
Como alternativa, uma fábrica cliente pode ser configurada com SubdirectoryHandler usando AddHttpMessageHandler.
Tempo limite de chamada gRPC a partir de HttpClient.Timeout
HttpClient é configurado com um tempo limite de 100 segundos por padrão. Se um GrpcChannel estiver configurado para usar um HttpClient, as chamadas de transmissão gRPC de longa duração serão canceladas se não forem concluídas dentro do limite de tempo.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Há algumas maneiras de corrigir esse erro. A primeira é configurar HttpClient.Timeout para um valor maior. Timeout.InfiniteTimeSpan Desativa o tempo limite:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(handler) { Timeout = Timeout.InfiniteTimeSpan };
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Greeter.GreeterClient(channel);
Como alternativa, evite criar HttpClient e definir GrpcChannel.HttpHandler :
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);
Este documento discute problemas comumente encontrados ao desenvolver aplicativos gRPC no .NET.
Incompatibilidade entre a configuração SSL/TLS do cliente e do serviço
O modelo gRPC e os exemplos usam Transport Layer Security (TLS) para proteger serviços gRPC por padrão. Os clientes gRPC precisam usar uma conexão segura para chamar serviços gRPC seguros com êxito.
Você pode verificar se o serviço gRPC ASP.NET Core está usando TLS nos logs gravados na inicialização do aplicativo. O serviço estará a escutar num endpoint HTTPS.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
O cliente .NET deve usar https no endereço do servidor para fazer chamadas com uma conexão segura:
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greet.GreeterClient(channel);
}
Todas as implementações de cliente gRPC suportam TLS. Os clientes gRPC de outros idiomas normalmente exigem o canal configurado com SslCredentials.
SslCredentials Especifica o certificado que o cliente usará e ele deve ser usado em vez de credenciais inseguras. Para obter exemplos de configuração das diferentes implementações de cliente gRPC para usar TLS, consulte Autenticação gRPC.
Chamar um serviço gRPC com um certificado não confiável ou inválido
O cliente gRPC do .NET requer que o serviço tenha um certificado confiável. A seguinte mensagem de erro é retornada ao chamar um serviço gRPC sem um certificado confiável:
Exceção não tratada. System.Net.Http.HttpRequestException: A conexão SSL não pôde ser estabelecida, consulte exceção interna. >--- System.Security.Authentication.AuthenticationException: O certificado remoto é inválido de acordo com o procedimento de validação.
Você poderá ver esse erro se estiver testando seu aplicativo localmente e o certificado de desenvolvimento HTTPS ASP.NET Core não for confiável. Para obter instruções para corrigir esse problema, consulte Confiar no certificado de desenvolvimento HTTPS do ASP.NET Core no Windows e macOS.
Se você estiver chamando um serviço gRPC em outra máquina e não puder confiar no certificado, o cliente gRPC poderá ser configurado para ignorar o certificado inválido. O código a seguir usa HttpClientHandler.ServerCertificateCustomValidationCallback para permitir chamadas sem um certificado confiável:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
A fábrica do cliente gRPC permite chamadas sem um certificado confiável. Use o ConfigurePrimaryHttpMessageHandler método de extensão para configurar o manipulador no cliente.
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Warning
Os certificados não confiáveis só devem ser usados durante o desenvolvimento do aplicativo. Os aplicativos de produção devem sempre usar certificados válidos.
Chamar serviços gRPC inseguros com cliente .NET
O cliente gRPC .NET pode chamar serviços gRPC inseguros especificando http o endereço do servidor. Por exemplo, GrpcChannel.ForAddress("http://localhost:5000").
Há alguns requisitos adicionais para chamar serviços gRPC inseguros, dependendo da versão .NET que um aplicativo está usando:
O .NET 5 ou posterior requer Grpc.Net.Client versão 2.32.0 ou posterior.
O .NET Core 3.x requer configuração adicional. A aplicação deve definir o interruptor
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupportparatrue:// This switch must be set before creating the GrpcChannel/HttpClient. AppContext.SetSwitch( "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); // The port number(5000) must match the port of the gRPC server. var channel = GrpcChannel.ForAddress("http://localhost:5000"); var client = new Greet.GreeterClient(channel);
A opção só é necessária para o System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport .NET Core 3.x. Ele não faz nada no .NET 5 e não é necessário.
Important
Os serviços gRPC inseguros devem ser hospedados em uma porta somente HTTP/2. Para obter mais informações, consulte ASP.NET negociação de protocolo principal.
Não é possível iniciar ASP.NET aplicativo gRPC Core no macOS
Kestrel não suporta HTTP/2 com TLS no macOS antes do .NET 8. O modelo e os exemplos do ASP.NET Core gRPC usam TLS por padrão. Você verá a seguinte mensagem de erro ao tentar iniciar o servidor gRPC:
Não é possível ligar à interface de retorno IPv4 https://localhost:5001: 'HTTP/2 sobre TLS não é suportado no macOS devido à ausência de suporte ALPN.'.
Para contornar esse problema no .NET 7 ou anterior, configure Kestrel e o cliente gRPC para usar HTTP/2 sem TLS. Você só deve fazer isso durante o desenvolvimento. Não usar TLS resultará no envio de mensagens gRPC sem criptografia.
Kestrel deve configurar um ponto de extremidade HTTP/2 sem TLS em Program.cs:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(5000, o => o.Protocols =
HttpProtocols.Http2);
});
webBuilder.UseStartup<Startup>();
});
Quando um ponto de extremidade HTTP/2 é configurado sem TLS, ListenOptions.Protocols do ponto de extremidade deve ser definido como HttpProtocols.Http2.
HttpProtocols.Http1AndHttp2 não pode ser usado porque o TLS é necessário para negociar HTTP/2. Sem TLS, todas as ligações com o ponto de extremidade revertem para o padrão HTTP/1.1, e as chamadas gRPC falham.
O cliente gRPC também deve ser configurado para não usar TLS. Para obter mais informações, consulte Chamar serviços gRPC inseguros com cliente .NET.
Warning
HTTP/2 sem TLS só deve ser usado durante o desenvolvimento do aplicativo. Os aplicativos de produção devem sempre usar segurança de transporte. Para obter mais informações, consulte Considerações de segurança no gRPC para ASP.NET Core.
Os ativos gRPC C# não são código gerado a partir de .proto arquivos
A geração de código gRPC de clientes concretos e classes base de serviço requer que os ficheiros protobuf e as ferramentas sejam referenciados a partir de um projeto. Deve incluir:
-
.protoarquivos que pretende usar no grupo de itens<Protobuf>. Os arquivos importados.protodevem ser referenciados pelo projeto. - Referência de pacote para o pacote de ferramentas gRPC Grpc.Tools.
Para obter mais informações sobre como gerar ativos gRPC C#, consulte Serviços gRPC com C#.
Um aplicativo Web ASP.NET Core que hospeda serviços gRPC só precisa da classe base de serviço gerada:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Um aplicativo cliente gRPC que faz chamadas gRPC só precisa do cliente concreto gerado:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
Projetos WPF não são capazes de gerar ativos gRPC C# de arquivos .proto.
Os projetos WPF têm um problema conhecido que impede a geração de código gRPC de funcionar corretamente. Quaisquer tipos de gRPC gerados num projeto WPF por referência aos Grpc.Tools e .proto arquivos criarão erros de compilação quando usados:
erro CS0246: O tipo ou nome de namespace 'MyGrpcServices' não pôde ser encontrado (está a faltar uma diretiva using ou uma referência de assembly?)
Você pode solucionar esse problema da seguinte forma:
- Crie um novo projeto de biblioteca de classes .NET.
- No novo projeto, adicione referências para habilitar a geração de código C# a partir de
.protoarquivos:- Adicione as seguintes referências de pacote:
- Adicione
.protoarquivos ao grupo de<Protobuf>itens.
- No aplicativo WPF, adicione uma referência ao novo projeto.
A aplicação WPF pode usar os tipos gerados pelo gRPC do novo projeto de biblioteca de classes.
Chamando serviços gRPC hospedados em um subdiretório
Warning
Muitas ferramentas gRPC de terceiros não suportam serviços hospedados em subdiretórios. Considere encontrar uma maneira de hospedar gRPC como o diretório raiz.
O componente de caminho do endereço de um canal gRPC é ignorado ao fazer chamadas gRPC. Por exemplo, GrpcChannel.ForAddress("https://localhost:5001/ignored_path") não usará ignored_path ao rotear chamadas gRPC para o serviço.
O caminho de endereço é ignorado porque o gRPC tem uma estrutura de endereço padronizada e prescritiva. Um endereço gRPC combina os nomes de pacote, serviço e método: https://localhost:5001/PackageName.ServiceName/MethodName.
Há alguns cenários em que um aplicativo precisa incluir um caminho com chamadas gRPC. Por exemplo, quando um aplicativo gRPC ASP.NET Core é hospedado em um diretório do IIS e o diretório precisa ser incluído na solicitação. Quando um caminho é necessário, ele pode ser adicionado à chamada gRPC usando o personalizado SubdirectoryHandler especificado abaixo:
/// <summary>
/// A delegating handler that adds a subdirectory to the URI of gRPC requests.
/// </summary>
public class SubdirectoryHandler : DelegatingHandler
{
private readonly string _subdirectory;
public SubdirectoryHandler(HttpMessageHandler innerHandler, string subdirectory)
: base(innerHandler)
{
_subdirectory = subdirectory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler é usado quando o canal gRPC é criado.
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/MyApp");
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
O código anterior:
- Cria um
SubdirectoryHandlercom o caminho/MyApp. - Configura um canal para usar
SubdirectoryHandler. - Chama o serviço gRPC com
SayHelloAsync. A chamada gRPC é enviada parahttps://localhost:5001/MyApp/greet.Greeter/SayHello.
Como alternativa, uma fábrica cliente pode ser configurada com SubdirectoryHandler usando AddHttpMessageHandler.
Tempo limite de chamada gRPC a partir de HttpClient.Timeout
HttpClient é configurado com um tempo limite de 100 segundos por padrão. Se um GrpcChannel estiver configurado para usar um HttpClient, as chamadas de transmissão gRPC de longa duração serão canceladas se não forem concluídas dentro do limite de tempo.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Há algumas maneiras de corrigir esse erro. A primeira é configurar HttpClient.Timeout para um valor maior. Timeout.InfiniteTimeSpan Desativa o tempo limite:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(handler) { Timeout = Timeout.InfiniteTimeSpan };
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Greeter.GreeterClient(channel);
Como alternativa, evite criar HttpClient e definir GrpcChannel.HttpHandler :
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greeter.GreeterClient(channel);