Eventi
19 nov, 23 - 21 nov, 23
Partecipa alle sessioni online di Microsoft Ignite create per espandere le tue competenze e aiutarti a risolvere i problemi complessi di oggi.
Iscriviti subitoQuesto browser non è più supportato.
Esegui l'aggiornamento a Microsoft Edge per sfruttare i vantaggi di funzionalità più recenti, aggiornamenti della sicurezza e supporto tecnico.
Nota
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Avviso
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Importante
Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Questo documento illustra i problemi comunemente riscontrati durante lo sviluppo di app gRPC in .NET.
Il modello e gli esempi gRPC usano Transport Layer Security (TLS) per proteggere i servizi gRPC per impostazione predefinita. I client gRPC devono usare una connessione sicura per chiamare correttamente i servizi gRPC protetti.
È possibile verificare che il servizio ASP.NET Core gRPC usi TLS nei log scritti all'avvio dell'app. Il servizio sarà in ascolto su un 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
Il client .NET Core deve usare https
nell'indirizzo del server per effettuare chiamate con una connessione protetta:
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greeter.GreeterClient(channel);
Tutte le implementazioni del client gRPC supportano TLS. I client gRPC provenienti da altre lingue richiedono in genere il canale configurato con SslCredentials
. SslCredentials
specifica il certificato che verrà usato dal client e deve essere usato invece di credenziali non sicure. Per esempi di configurazione delle diverse implementazioni del client gRPC per l'uso di TLS, vedere Autenticazione gRPC.
Il client .NET gRPC richiede che il servizio disponga di un certificato attendibile. Quando si chiama un servizio gRPC senza un certificato attendibile, viene restituito il messaggio di errore seguente:
Eccezione non gestita. System.Net.Http.HttpRequestException: impossibile stabilire la connessione SSL, vedere l'eccezione interna. >--- System.Security.Authentication.AuthenticationException: il certificato remoto non è valido in base alla procedura di convalida.
Questo errore può verificarsi se si sta testando l'app in locale e il certificato di sviluppo HTTPS core ASP.NET non è attendibile. Per istruzioni su come risolvere questo problema, vedere Considerare attendibile il certificato di sviluppo di ASP.NET Core HTTPS in Windows e macOS.
Se si chiama un servizio gRPC in un altro computer e non è possibile considerare attendibile il certificato, il client gRPC può essere configurato per ignorare il certificato non valido. Il codice seguente usa HttpClientHandler.ServerCertificateCustomValidationCallback per consentire le chiamate senza un certificato attendibile:
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);
La factory client gRPC consente chiamate senza un certificato attendibile. Usare il ConfigurePrimaryHttpMessageHandler metodo di estensione per configurare il gestore nel client:
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;
});
Avviso
I certificati non attendibili devono essere usati solo durante lo sviluppo di app. Le app di produzione devono sempre usare certificati validi.
Il client .NET gRPC può chiamare servizi gRPC non sicuri specificando http
l'indirizzo del server. Ad esempio: GrpcChannel.ForAddress("http://localhost:5000")
.
Esistono alcuni requisiti aggiuntivi per chiamare servizi gRPC non sicuri a seconda della versione .NET usata da un'app:
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
su true
. Per altre informazioni, vedere Asp.Net Core 3.x: Chiamare servizi gRPC non sicuri con il client .NET:Importante
I servizi gRPC non sicuri devono essere ospitati in una porta solo HTTP/2. Per altre informazioni, vedere ASP.NET negoziazione del protocollo Core.
Kestrel non supporta HTTP/2 con TLS in macOS prima di .NET 8. Il modello ASP.NET Core gRPC e gli esempi usano TLS per impostazione predefinita. Quando si tenta di avviare il server gRPC, verrà visualizzato il messaggio di errore seguente:
Impossibile eseguire l'associazione a https://localhost:5001 nell'interfaccia di loopback IPv4: "HTTP/2 su TLS non è supportato in macOS a causa del supporto ALPN mancante".
Per risolvere questo problema in .NET 7 e versioni precedenti, configurare Kestrel e il client gRPC per usare HTTP/2 senza TLS. Questa operazione deve essere eseguita solo durante lo sviluppo. L'uso di TLS comporta l'invio di messaggi gRPC senza crittografia. Per altre informazioni, vedere Asp.Net Core 7.0: Impossibile avviare ASP.NET'app Core gRPC in macOS.
La generazione di codice gRPC di client concreti e classi di base del servizio richiede file protobuf e strumenti a cui fare riferimento da un progetto. È necessario includere:
.proto
file che si desidera utilizzare nel <Protobuf>
gruppo di elementi. I file importati .proto
devono fare riferimento al progetto.Per altre informazioni sulla generazione di asset GRPC C#, vedere gRPC services with C#.
Un'app Web ASP.NET Core che ospita i servizi gRPC richiede solo la classe di base del servizio generata:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Un'app client gRPC che effettua chiamate gRPC richiede solo il client concreto generato:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
I progetti WPF presentano un problema noto che impedisce il corretto funzionamento della generazione del codice gRPC. Tutti i tipi gRPC generati in un progetto WPF facendo riferimento ai file e .proto
creeranno errori di compilazione Grpc.Tools
quando vengono usati:
errore CS0246: Impossibile trovare il tipo o il nome dello spazio dei nomi 'MyGrpcServices' (manca una direttiva using o un riferimento all'assembly?)
Per risolvere questo problema, è possibile:
.proto
file: .proto
al gruppo di elementi <Protobuf>
.L'applicazione WPF può usare i tipi generati da gRPC dal nuovo progetto di libreria di classi.
Avviso
Molti strumenti gRPC di terze parti non supportano i servizi ospitati nelle sottodirectory. Valutare la possibilità di trovare un modo per ospitare gRPC come directory radice.
Il componente del percorso dell'indirizzo di un canale gRPC viene ignorato durante l'esecuzione di chiamate gRPC. Ad esempio, GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
non verrà usato ignored_path
quando si instradano chiamate gRPC per il servizio.
Il percorso dell'indirizzo viene ignorato perché gRPC ha una struttura di indirizzi prescrittiva standardizzata. Un indirizzo gRPC combina il pacchetto, il servizio e i nomi dei metodi: https://localhost:5001/PackageName.ServiceName/MethodName
.
Esistono alcuni scenari in cui un'app deve includere un percorso con chiamate gRPC. Ad esempio, quando un'app ASP.NET Core gRPC è ospitata in una directory IIS e la directory deve essere inclusa nella richiesta. Quando è necessario un percorso, può essere aggiunto alla chiamata gRPC usando l'opzione personalizzata SubdirectoryHandler
specificata di seguito:
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
viene usato quando viene creato il canale gRPC.
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" });
Il codice precedente:
SubdirectoryHandler
oggetto con il percorso /MyApp
.SubdirectoryHandler
.SayHelloAsync
. La chiamata gRPC viene inviata a https://localhost:5001/MyApp/greet.Greeter/SayHello
.In alternativa, una factory client può essere configurata con SubdirectoryHandler
usando AddHttpMessageHandler.
Il client .NET gRPC supporta HTTP/3 con .NET 6 o versione successiva. Se il server invia un'intestazione alt-svc
di risposta al client che indica che il server supporta HTTP/3, il client aggiornerà automaticamente la connessione a HTTP/3. Per altre informazioni, vedere Usare HTTP/3 con il server Web ASP.NET CoreKestrel.
Un DelegatingHandler oggetto può essere usato per forzare l'uso di HTTP/3 da parte di un client gRPC. L'uso forzato di HTTP/3 evita il sovraccarico dell'aggiornamento della richiesta. Forzare HTTP/3 con codice simile al seguente:
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
viene usato quando viene creato il canale gRPC. Il codice seguente crea un canale configurato per l'uso di 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" });
In alternativa, una factory client può essere configurata con Http3Handler
usando AddHttpMessageHandler.
Il Grpc.Tools
pacchetto genera tipi .NET dai .proto
file usando un file binario nativo in bundle denominato protoc
. Sono necessari passaggi aggiuntivi per compilare app gRPC su piattaforme non supportate dai file binari nativi in Grpc.Tools
, ad esempio Alpine Linux.
Una soluzione consiste nel generare codice in anticipo.
.proto
i file e il riferimento al Grpc.Tools
pacchetto a un nuovo progetto.Con i passaggi precedenti, l'app non richiede Grpc.Tools
più la compilazione perché il codice viene generato in anticipo.
Grpc.Tools
supporta l'uso di file binari nativi personalizzati. Questa funzionalità consente l'esecuzione degli strumenti gRPC negli ambienti in cui i file binari nativi in bundle non supportano.
Compilare o acquisire protoc
file grpc_csharp_plugin
binari nativi e configurarli Grpc.Tools
per usarli. Configurare i file binari nativi impostando le variabili di ambiente seguenti:
PROTOBUF_PROTOC
- Percorso completo del compilatore di buffer del protocolloGRPC_PROTOC_PLUGIN
- Percorso completo del grpc_csharp_pluginPer Alpine Linux, sono disponibili pacchetti forniti dalla community per il compilatore di buffer del protocollo e i plug-in gRPC all'indirizzo 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
Per altre informazioni sull'uso Grpc.Tools
di con architetture non supportate, vedere la documentazione sull'integrazione della compilazione gRPC.
HttpClient è configurato con un timeout di 100 secondi per impostazione predefinita. Se un GrpcChannel
oggetto è configurato per l'uso di un HttpClient
oggetto , le chiamate di streaming gRPC a esecuzione prolungata vengono annullate se non vengono completate entro il limite di timeout.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Esistono due modi per correggere l'errore. Il primo consiste nel configurare HttpClient.Timeout un valore maggiore. Timeout.InfiniteTimeSpan disabilita il timeout:
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);
In alternativa, evitare di creare HttpClient
e impostare 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);
Questo documento illustra i problemi comunemente riscontrati durante lo sviluppo di app gRPC in .NET.
Il modello e gli esempi gRPC usano Transport Layer Security (TLS) per proteggere i servizi gRPC per impostazione predefinita. I client gRPC devono usare una connessione sicura per chiamare correttamente i servizi gRPC protetti.
È possibile verificare che il servizio ASP.NET Core gRPC usi TLS nei log scritti all'avvio dell'app. Il servizio sarà in ascolto su un 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
Il client .NET Core deve usare https
nell'indirizzo del server per effettuare chiamate con una connessione protetta:
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);
}
Tutte le implementazioni del client gRPC supportano TLS. I client gRPC provenienti da altre lingue richiedono in genere il canale configurato con SslCredentials
. SslCredentials
specifica il certificato che verrà usato dal client e deve essere usato invece di credenziali non sicure. Per esempi di configurazione delle diverse implementazioni del client gRPC per l'uso di TLS, vedere Autenticazione gRPC.
Il client .NET gRPC richiede che il servizio disponga di un certificato attendibile. Quando si chiama un servizio gRPC senza un certificato attendibile, viene restituito il messaggio di errore seguente:
Eccezione non gestita. System.Net.Http.HttpRequestException: impossibile stabilire la connessione SSL, vedere l'eccezione interna. >--- System.Security.Authentication.AuthenticationException: il certificato remoto non è valido in base alla procedura di convalida.
Questo errore può verificarsi se si sta testando l'app in locale e il certificato di sviluppo HTTPS core ASP.NET non è attendibile. Per istruzioni su come risolvere questo problema, vedere Considerare attendibile il certificato di sviluppo di ASP.NET Core HTTPS in Windows e macOS.
Se si chiama un servizio gRPC in un altro computer e non è possibile considerare attendibile il certificato, il client gRPC può essere configurato per ignorare il certificato non valido. Il codice seguente usa HttpClientHandler.ServerCertificateCustomValidationCallback per consentire le chiamate senza un certificato attendibile:
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);
La factory client gRPC consente chiamate senza un certificato attendibile. Usare il ConfigurePrimaryHttpMessageHandler metodo di estensione per configurare il gestore nel client:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Avviso
I certificati non attendibili devono essere usati solo durante lo sviluppo di app. Le app di produzione devono sempre usare certificati validi.
Il client .NET gRPC può chiamare servizi gRPC non sicuri specificando http
l'indirizzo del server. Ad esempio: GrpcChannel.ForAddress("http://localhost:5000")
.
Esistono alcuni requisiti aggiuntivi per chiamare servizi gRPC non sicuri a seconda della versione .NET usata da un'app:
.NET 5 o versione successiva richiede Grpc.Net.Client versione 2.32.0 o successiva.
.NET Core 3.x richiede una configurazione aggiuntiva. L'app deve impostare l'opzione System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
su true
:
// 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);
L'opzione System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
è necessaria solo per .NET Core 3.x. Non esegue alcuna operazione in .NET 5 e non è necessaria.
Importante
I servizi gRPC non sicuri devono essere ospitati in una porta solo HTTP/2. Per altre informazioni, vedere ASP.NET negoziazione del protocollo Core.
Kestrel non supporta HTTP/2 con TLS in macOS prima di .NET 8. Il modello ASP.NET Core gRPC e gli esempi usano TLS per impostazione predefinita. Quando si tenta di avviare il server gRPC, verrà visualizzato il messaggio di errore seguente:
Impossibile eseguire l'associazione a https://localhost:5001 nell'interfaccia di loopback IPv4: "HTTP/2 su TLS non è supportato in macOS a causa del supporto ALPN mancante".
Per risolvere questo problema in .NET 7 e versioni precedenti, configurare Kestrel e il client gRPC per usare HTTP/2 senza TLS. Questa operazione deve essere eseguita solo durante lo sviluppo. L'uso di TLS comporta l'invio di messaggi gRPC senza crittografia.
Kestrel deve configurare un endpoint HTTP/2 senza TLS in 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);
});
5287
di porta localhost con il HTTP
numero di porta (non HTTPS
) specificato nel Properties/launchSettings.json
progetto di servizio gRPC.Quando un endpoint HTTP/2 è configurato senza TLS, l'endpoint ListenOptions.Protocols deve essere impostato su HttpProtocols.Http2
. HttpProtocols.Http1AndHttp2
non può essere usato perché TLS è necessario per negoziare HTTP/2. Senza TLS, tutte le connessioni all'endpoint sono predefinite HTTP/1.1 e le chiamate gRPC hanno esito negativo.
Il client gRPC deve anche essere configurato per non usare TLS. Per altre informazioni, vedere Chiamare servizi gRPC non sicuri con il client .NET Core.
Avviso
HTTP/2 senza TLS deve essere usato solo durante lo sviluppo di app. Le app di produzione devono sempre usare la sicurezza del trasporto. Per altre informazioni, vedere Considerazioni sulla sicurezza in gRPC per ASP.NET Core.
La generazione di codice gRPC di client concreti e classi di base del servizio richiede file protobuf e strumenti a cui fare riferimento da un progetto. È necessario includere:
.proto
file che si desidera utilizzare nel <Protobuf>
gruppo di elementi. I file importati .proto
devono fare riferimento al progetto.Per altre informazioni sulla generazione di asset GRPC C#, vedere gRPC services with C#.
Un'app Web ASP.NET Core che ospita i servizi gRPC richiede solo la classe di base del servizio generata:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Un'app client gRPC che effettua chiamate gRPC richiede solo il client concreto generato:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
I progetti WPF presentano un problema noto che impedisce il corretto funzionamento della generazione del codice gRPC. Tutti i tipi gRPC generati in un progetto WPF facendo riferimento ai file e .proto
creeranno errori di compilazione Grpc.Tools
quando vengono usati:
errore CS0246: Impossibile trovare il tipo o il nome dello spazio dei nomi 'MyGrpcServices' (manca una direttiva using o un riferimento all'assembly?)
Per risolvere questo problema, è possibile:
.proto
file: .proto
al gruppo di elementi <Protobuf>
.L'applicazione WPF può usare i tipi generati da gRPC dal nuovo progetto di libreria di classi.
Avviso
Molti strumenti gRPC di terze parti non supportano i servizi ospitati nelle sottodirectory. Valutare la possibilità di trovare un modo per ospitare gRPC come directory radice.
Il componente del percorso dell'indirizzo di un canale gRPC viene ignorato durante l'esecuzione di chiamate gRPC. Ad esempio, GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
non verrà usato ignored_path
quando si instradano chiamate gRPC per il servizio.
Il percorso dell'indirizzo viene ignorato perché gRPC ha una struttura di indirizzi prescrittiva standardizzata. Un indirizzo gRPC combina il pacchetto, il servizio e i nomi dei metodi: https://localhost:5001/PackageName.ServiceName/MethodName
.
Esistono alcuni scenari in cui un'app deve includere un percorso con chiamate gRPC. Ad esempio, quando un'app ASP.NET Core gRPC è ospitata in una directory IIS e la directory deve essere inclusa nella richiesta. Quando è necessario un percorso, può essere aggiunto alla chiamata gRPC usando l'opzione personalizzata SubdirectoryHandler
specificata di seguito:
/// <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
viene usato quando viene creato il canale gRPC.
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" });
Il codice precedente:
SubdirectoryHandler
oggetto con il percorso /MyApp
.SubdirectoryHandler
.SayHelloAsync
. La chiamata gRPC viene inviata a https://localhost:5001/MyApp/greet.Greeter/SayHello
.In alternativa, una factory client può essere configurata con SubdirectoryHandler
usando AddHttpMessageHandler.
Il client .NET gRPC supporta HTTP/3 con .NET 6 o versione successiva. Se il server invia un'intestazione alt-svc
di risposta al client che indica che il server supporta HTTP/3, il client aggiornerà automaticamente la connessione a HTTP/3. Per informazioni su come abilitare HTTP/3 nel server, vedere Usare HTTP/3 con il server Web ASP.NET CoreKestrel.
Il supporto HTTP/3 in .NET 8 è abilitato per impostazione predefinita. Il supporto HTTP/3 in .NET 6 e .NET 7 deve essere abilitato tramite un flag di configurazione nel file di progetto:
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Net.SocketsHttpHandler.Http3Support" Value="true" />
</ItemGroup>
System.Net.SocketsHttpHandler.Http3Support
può anche essere impostato usando AppContext.SetSwitch.
Un DelegatingHandler oggetto può essere usato per forzare l'uso di HTTP/3 da parte di un client gRPC. L'uso forzato di HTTP/3 evita il sovraccarico dell'aggiornamento della richiesta. Forzare HTTP/3 con codice simile al seguente:
/// <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
viene usato quando viene creato il canale gRPC. Il codice seguente crea un canale configurato per l'uso di 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" });
In alternativa, una factory client può essere configurata con Http3Handler
usando AddHttpMessageHandler.
Il Grpc.Tools
pacchetto genera tipi .NET dai .proto
file usando un file binario nativo in bundle denominato protoc
. Sono necessari passaggi aggiuntivi per compilare app gRPC su piattaforme non supportate dai file binari nativi in Grpc.Tools
, ad esempio Alpine Linux.
Una soluzione consiste nel generare codice in anticipo.
.proto
i file e il riferimento al Grpc.Tools
pacchetto a un nuovo progetto.Con i passaggi precedenti, l'app non richiede Grpc.Tools
più la compilazione perché il codice viene generato in anticipo.
Grpc.Tools
supporta l'uso di file binari nativi personalizzati. Questa funzionalità consente l'esecuzione degli strumenti gRPC negli ambienti in cui i file binari nativi in bundle non supportano.
Compilare o acquisire protoc
file grpc_csharp_plugin
binari nativi e configurarli Grpc.Tools
per usarli. Configurare i file binari nativi impostando le variabili di ambiente seguenti:
PROTOBUF_PROTOC
- Percorso completo del compilatore di buffer del protocolloGRPC_PROTOC_PLUGIN
- Percorso completo del grpc_csharp_pluginPer Alpine Linux, sono disponibili pacchetti forniti dalla community per il compilatore di buffer del protocollo e i plug-in gRPC all'indirizzo 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
Per altre informazioni sull'uso Grpc.Tools
di con architetture non supportate, vedere la documentazione sull'integrazione della compilazione gRPC.
HttpClient è configurato con un timeout di 100 secondi per impostazione predefinita. Se un GrpcChannel
oggetto è configurato per l'uso di un HttpClient
oggetto , le chiamate di streaming gRPC a esecuzione prolungata vengono annullate se non vengono completate entro il limite di timeout.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Esistono due modi per correggere l'errore. Il primo consiste nel configurare HttpClient.Timeout un valore maggiore. Timeout.InfiniteTimeSpan disabilita il timeout:
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);
In alternativa, evitare di creare HttpClient
e impostare 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);
Questo documento illustra i problemi comunemente riscontrati durante lo sviluppo di app gRPC in .NET.
Il modello e gli esempi gRPC usano Transport Layer Security (TLS) per proteggere i servizi gRPC per impostazione predefinita. I client gRPC devono usare una connessione sicura per chiamare correttamente i servizi gRPC protetti.
È possibile verificare che il servizio ASP.NET Core gRPC usi TLS nei log scritti all'avvio dell'app. Il servizio sarà in ascolto su un 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
Il client .NET Core deve usare https
nell'indirizzo del server per effettuare chiamate con una connessione protetta:
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);
}
Tutte le implementazioni del client gRPC supportano TLS. I client gRPC provenienti da altre lingue richiedono in genere il canale configurato con SslCredentials
. SslCredentials
specifica il certificato che verrà usato dal client e deve essere usato invece di credenziali non sicure. Per esempi di configurazione delle diverse implementazioni del client gRPC per l'uso di TLS, vedere Autenticazione gRPC.
Il client .NET gRPC richiede che il servizio disponga di un certificato attendibile. Quando si chiama un servizio gRPC senza un certificato attendibile, viene restituito il messaggio di errore seguente:
Eccezione non gestita. System.Net.Http.HttpRequestException: impossibile stabilire la connessione SSL, vedere l'eccezione interna. >--- System.Security.Authentication.AuthenticationException: il certificato remoto non è valido in base alla procedura di convalida.
Questo errore può verificarsi se si sta testando l'app in locale e il certificato di sviluppo HTTPS core ASP.NET non è attendibile. Per istruzioni su come risolvere questo problema, vedere Considerare attendibile il certificato di sviluppo di ASP.NET Core HTTPS in Windows e macOS.
Se si chiama un servizio gRPC in un altro computer e non è possibile considerare attendibile il certificato, il client gRPC può essere configurato per ignorare il certificato non valido. Il codice seguente usa HttpClientHandler.ServerCertificateCustomValidationCallback per consentire le chiamate senza un certificato attendibile:
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);
La factory client gRPC consente chiamate senza un certificato attendibile. Usare il ConfigurePrimaryHttpMessageHandler metodo di estensione per configurare il gestore nel client:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Avviso
I certificati non attendibili devono essere usati solo durante lo sviluppo di app. Le app di produzione devono sempre usare certificati validi.
Il client .NET gRPC può chiamare servizi gRPC non sicuri specificando http
l'indirizzo del server. Ad esempio: GrpcChannel.ForAddress("http://localhost:5000")
.
Esistono alcuni requisiti aggiuntivi per chiamare servizi gRPC non sicuri a seconda della versione .NET usata da un'app:
.NET 5 o versione successiva richiede Grpc.Net.Client versione 2.32.0 o successiva.
.NET Core 3.x richiede una configurazione aggiuntiva. L'app deve impostare l'opzione System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
su true
:
// 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);
L'opzione System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
è necessaria solo per .NET Core 3.x. Non esegue alcuna operazione in .NET 5 e non è necessaria.
Importante
I servizi gRPC non sicuri devono essere ospitati in una porta solo HTTP/2. Per altre informazioni, vedere ASP.NET negoziazione del protocollo Core.
Kestrel non supporta HTTP/2 con TLS in macOS prima di .NET 8. Il modello ASP.NET Core gRPC e gli esempi usano TLS per impostazione predefinita. Quando si tenta di avviare il server gRPC, verrà visualizzato il messaggio di errore seguente:
Impossibile eseguire l'associazione a https://localhost:5001 nell'interfaccia di loopback IPv4: "HTTP/2 su TLS non è supportato in macOS a causa del supporto ALPN mancante".
Per risolvere questo problema in .NET 7 e versioni precedenti, configurare Kestrel e il client gRPC per usare HTTP/2 senza TLS. Questa operazione deve essere eseguita solo durante lo sviluppo. L'uso di TLS comporta l'invio di messaggi gRPC senza crittografia.
Kestrel deve configurare un endpoint HTTP/2 senza TLS in 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 un endpoint HTTP/2 è configurato senza TLS, l'endpoint ListenOptions.Protocols deve essere impostato su HttpProtocols.Http2
. HttpProtocols.Http1AndHttp2
non può essere usato perché TLS è necessario per negoziare HTTP/2. Senza TLS, tutte le connessioni all'endpoint sono predefinite HTTP/1.1 e le chiamate gRPC hanno esito negativo.
Il client gRPC deve anche essere configurato per non usare TLS. Per altre informazioni, vedere Chiamare servizi gRPC non sicuri con il client .NET Core.
Avviso
HTTP/2 senza TLS deve essere usato solo durante lo sviluppo di app. Le app di produzione devono sempre usare la sicurezza del trasporto. Per altre informazioni, vedere Considerazioni sulla sicurezza in gRPC per ASP.NET Core.
La generazione di codice gRPC di client concreti e classi di base del servizio richiede file protobuf e strumenti a cui fare riferimento da un progetto. È necessario includere:
.proto
file che si desidera utilizzare nel <Protobuf>
gruppo di elementi. I file importati .proto
devono fare riferimento al progetto.Per altre informazioni sulla generazione di asset GRPC C#, vedere gRPC services with C#.
Un'app Web ASP.NET Core che ospita i servizi gRPC richiede solo la classe di base del servizio generata:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Un'app client gRPC che effettua chiamate gRPC richiede solo il client concreto generato:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
I progetti WPF presentano un problema noto che impedisce il corretto funzionamento della generazione del codice gRPC. Tutti i tipi gRPC generati in un progetto WPF facendo riferimento ai file e .proto
creeranno errori di compilazione Grpc.Tools
quando vengono usati:
errore CS0246: Impossibile trovare il tipo o il nome dello spazio dei nomi 'MyGrpcServices' (manca una direttiva using o un riferimento all'assembly?)
Per risolvere questo problema, è possibile:
.proto
file: .proto
al gruppo di elementi <Protobuf>
.L'applicazione WPF può usare i tipi generati da gRPC dal nuovo progetto di libreria di classi.
Avviso
Molti strumenti gRPC di terze parti non supportano i servizi ospitati nelle sottodirectory. Valutare la possibilità di trovare un modo per ospitare gRPC come directory radice.
Il componente del percorso dell'indirizzo di un canale gRPC viene ignorato durante l'esecuzione di chiamate gRPC. Ad esempio, GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
non verrà usato ignored_path
quando si instradano chiamate gRPC per il servizio.
Il percorso dell'indirizzo viene ignorato perché gRPC ha una struttura di indirizzi prescrittiva standardizzata. Un indirizzo gRPC combina il pacchetto, il servizio e i nomi dei metodi: https://localhost:5001/PackageName.ServiceName/MethodName
.
Esistono alcuni scenari in cui un'app deve includere un percorso con chiamate gRPC. Ad esempio, quando un'app ASP.NET Core gRPC è ospitata in una directory IIS e la directory deve essere inclusa nella richiesta. Quando è necessario un percorso, può essere aggiunto alla chiamata gRPC usando l'opzione personalizzata SubdirectoryHandler
specificata di seguito:
/// <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
viene usato quando viene creato il canale gRPC.
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" });
Il codice precedente:
SubdirectoryHandler
oggetto con il percorso /MyApp
.SubdirectoryHandler
.SayHelloAsync
. La chiamata gRPC viene inviata a https://localhost:5001/MyApp/greet.Greeter/SayHello
.In alternativa, una factory client può essere configurata con SubdirectoryHandler
usando AddHttpMessageHandler.
HttpClient è configurato con un timeout di 100 secondi per impostazione predefinita. Se un GrpcChannel
oggetto è configurato per l'uso di un HttpClient
oggetto , le chiamate di streaming gRPC a esecuzione prolungata vengono annullate se non vengono completate entro il limite di timeout.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Esistono due modi per correggere l'errore. Il primo consiste nel configurare HttpClient.Timeout un valore maggiore. Timeout.InfiniteTimeSpan disabilita il timeout:
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);
In alternativa, evitare di creare HttpClient
e impostare 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);
Questo documento illustra i problemi comunemente riscontrati durante lo sviluppo di app gRPC in .NET.
Il modello e gli esempi gRPC usano Transport Layer Security (TLS) per proteggere i servizi gRPC per impostazione predefinita. I client gRPC devono usare una connessione sicura per chiamare correttamente i servizi gRPC protetti.
È possibile verificare che il servizio ASP.NET Core gRPC usi TLS nei log scritti all'avvio dell'app. Il servizio sarà in ascolto su un 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
Il client .NET Core deve usare https
nell'indirizzo del server per effettuare chiamate con una connessione protetta:
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);
}
Tutte le implementazioni del client gRPC supportano TLS. I client gRPC provenienti da altre lingue richiedono in genere il canale configurato con SslCredentials
. SslCredentials
specifica il certificato che verrà usato dal client e deve essere usato invece di credenziali non sicure. Per esempi di configurazione delle diverse implementazioni del client gRPC per l'uso di TLS, vedere Autenticazione gRPC.
Il client .NET gRPC richiede che il servizio disponga di un certificato attendibile. Quando si chiama un servizio gRPC senza un certificato attendibile, viene restituito il messaggio di errore seguente:
Eccezione non gestita. System.Net.Http.HttpRequestException: impossibile stabilire la connessione SSL, vedere l'eccezione interna. >--- System.Security.Authentication.AuthenticationException: il certificato remoto non è valido in base alla procedura di convalida.
Questo errore può verificarsi se si sta testando l'app in locale e il certificato di sviluppo HTTPS core ASP.NET non è attendibile. Per istruzioni su come risolvere questo problema, vedere Considerare attendibile il certificato di sviluppo di ASP.NET Core HTTPS in Windows e macOS.
Se si chiama un servizio gRPC in un altro computer e non è possibile considerare attendibile il certificato, il client gRPC può essere configurato per ignorare il certificato non valido. Il codice seguente usa HttpClientHandler.ServerCertificateCustomValidationCallback per consentire le chiamate senza un certificato attendibile:
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);
La factory client gRPC consente chiamate senza un certificato attendibile. Usare il ConfigurePrimaryHttpMessageHandler metodo di estensione per configurare il gestore nel client:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
Avviso
I certificati non attendibili devono essere usati solo durante lo sviluppo di app. Le app di produzione devono sempre usare certificati validi.
Il client .NET gRPC può chiamare servizi gRPC non sicuri specificando http
l'indirizzo del server. Ad esempio: GrpcChannel.ForAddress("http://localhost:5000")
.
Esistono alcuni requisiti aggiuntivi per chiamare servizi gRPC non sicuri a seconda della versione .NET usata da un'app:
.NET 5 o versione successiva richiede Grpc.Net.Client versione 2.32.0 o successiva.
.NET Core 3.x richiede una configurazione aggiuntiva. L'app deve impostare l'opzione System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
su true
:
// 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);
L'opzione System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
è necessaria solo per .NET Core 3.x. Non esegue alcuna operazione in .NET 5 e non è necessaria.
Importante
I servizi gRPC non sicuri devono essere ospitati in una porta solo HTTP/2. Per altre informazioni, vedere ASP.NET negoziazione del protocollo Core.
Kestrel non supporta HTTP/2 con TLS in macOS prima di .NET 8. Il modello ASP.NET Core gRPC e gli esempi usano TLS per impostazione predefinita. Quando si tenta di avviare il server gRPC, verrà visualizzato il messaggio di errore seguente:
Impossibile eseguire l'associazione a https://localhost:5001 nell'interfaccia di loopback IPv4: "HTTP/2 su TLS non è supportato in macOS a causa del supporto ALPN mancante".
Per risolvere questo problema in .NET 7 e versioni precedenti, configurare Kestrel e il client gRPC per usare HTTP/2 senza TLS. Questa operazione deve essere eseguita solo durante lo sviluppo. L'uso di TLS comporta l'invio di messaggi gRPC senza crittografia.
Kestrel deve configurare un endpoint HTTP/2 senza TLS in 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 un endpoint HTTP/2 è configurato senza TLS, l'endpoint ListenOptions.Protocols deve essere impostato su HttpProtocols.Http2
. HttpProtocols.Http1AndHttp2
non può essere usato perché TLS è necessario per negoziare HTTP/2. Senza TLS, tutte le connessioni all'endpoint sono predefinite HTTP/1.1 e le chiamate gRPC hanno esito negativo.
Il client gRPC deve anche essere configurato per non usare TLS. Per altre informazioni, vedere Chiamare servizi gRPC non sicuri con il client .NET Core.
Avviso
HTTP/2 senza TLS deve essere usato solo durante lo sviluppo di app. Le app di produzione devono sempre usare la sicurezza del trasporto. Per altre informazioni, vedere Considerazioni sulla sicurezza in gRPC per ASP.NET Core.
La generazione di codice gRPC di client concreti e classi di base del servizio richiede file protobuf e strumenti a cui fare riferimento da un progetto. È necessario includere:
.proto
file che si desidera utilizzare nel <Protobuf>
gruppo di elementi. I file importati .proto
devono fare riferimento al progetto.Per altre informazioni sulla generazione di asset GRPC C#, vedere gRPC services with C#.
Un'app Web ASP.NET Core che ospita i servizi gRPC richiede solo la classe di base del servizio generata:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
Un'app client gRPC che effettua chiamate gRPC richiede solo il client concreto generato:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
I progetti WPF presentano un problema noto che impedisce il corretto funzionamento della generazione del codice gRPC. Tutti i tipi gRPC generati in un progetto WPF facendo riferimento ai file e .proto
creeranno errori di compilazione Grpc.Tools
quando vengono usati:
errore CS0246: Impossibile trovare il tipo o il nome dello spazio dei nomi 'MyGrpcServices' (manca una direttiva using o un riferimento all'assembly?)
Per risolvere questo problema, è possibile:
.proto
file: .proto
al gruppo di elementi <Protobuf>
.L'applicazione WPF può usare i tipi generati da gRPC dal nuovo progetto di libreria di classi.
Avviso
Molti strumenti gRPC di terze parti non supportano i servizi ospitati nelle sottodirectory. Valutare la possibilità di trovare un modo per ospitare gRPC come directory radice.
Il componente del percorso dell'indirizzo di un canale gRPC viene ignorato durante l'esecuzione di chiamate gRPC. Ad esempio, GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
non verrà usato ignored_path
quando si instradano chiamate gRPC per il servizio.
Il percorso dell'indirizzo viene ignorato perché gRPC ha una struttura di indirizzi prescrittiva standardizzata. Un indirizzo gRPC combina il pacchetto, il servizio e i nomi dei metodi: https://localhost:5001/PackageName.ServiceName/MethodName
.
Esistono alcuni scenari in cui un'app deve includere un percorso con chiamate gRPC. Ad esempio, quando un'app ASP.NET Core gRPC è ospitata in una directory IIS e la directory deve essere inclusa nella richiesta. Quando è necessario un percorso, può essere aggiunto alla chiamata gRPC usando l'opzione personalizzata SubdirectoryHandler
specificata di seguito:
/// <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
viene usato quando viene creato il canale gRPC.
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" });
Il codice precedente:
SubdirectoryHandler
oggetto con il percorso /MyApp
.SubdirectoryHandler
.SayHelloAsync
. La chiamata gRPC viene inviata a https://localhost:5001/MyApp/greet.Greeter/SayHello
.In alternativa, una factory client può essere configurata con SubdirectoryHandler
usando AddHttpMessageHandler.
HttpClient è configurato con un timeout di 100 secondi per impostazione predefinita. Se un GrpcChannel
oggetto è configurato per l'uso di un HttpClient
oggetto , le chiamate di streaming gRPC a esecuzione prolungata vengono annullate se non vengono completate entro il limite di timeout.
System.OperationCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
Esistono due modi per correggere l'errore. Il primo consiste nel configurare HttpClient.Timeout un valore maggiore. Timeout.InfiniteTimeSpan disabilita il timeout:
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);
In alternativa, evitare di creare HttpClient
e impostare 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);
Feedback su ASP.NET Core
ASP.NET Core è un progetto di open source. Selezionare un collegamento per fornire feedback:
Eventi
19 nov, 23 - 21 nov, 23
Partecipa alle sessioni online di Microsoft Ignite create per espandere le tue competenze e aiutarti a risolvere i problemi complessi di oggi.
Iscriviti subitoFormazione
Percorso di apprendimento
Creare app e servizi nativi del cloud con .NET e ASP.NET Core - Training
Creare app e servizi indipendenti distribuibili, altamente scalabili e resilienti usando la piattaforma .NET gratuita e open source. Con .NET è possibile usare la tecnologia di microservizi più diffusa, ad esempio Docker, Kubernetes, Dapr, Registro Azure Container e altro ancora per .NET e ASP.NET Servizi e applicazioni Core.