Gestione degli errori con gRPC
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 articolo illustra la gestione degli errori e gRPC:
- Funzionalità di gestione degli errori predefinite che usano i codici di stato gRPC e i messaggi di errore.
- Invio di informazioni di errore complesse e strutturate tramite la gestione degli errori avanzata.
Gestione degli errori predefinita
Le chiamate gRPC comunicano l'esito positivo o negativo con un codice di stato. Quando una chiamata gRPC viene completata correttamente, il server restituisce OK
uno stato al client. Se si verifica un errore, gRPC restituisce:
- Codice di stato dell'errore, ad esempio
CANCELLED
oUNAVAILABLE
. - Messaggio di errore di stringa facoltativo.
I tipi comunemente usati con la gestione degli errori sono:
StatusCode
: enumerazione dei codici di stato gRPC.OK
segnali di successo; altri valori sono un errore.Status
: oggettostruct
che combina unStatusCode
e un messaggio di errore di stringa facoltativo. Il messaggio di errore fornisce altri dettagli su ciò che è accaduto.RpcException
: tipo di eccezione conStatus
valore. Questa eccezione viene generata nei metodi del server gRPC e rilevata dai client gRPC.
La gestione degli errori predefinita supporta solo un codice di stato e una descrizione stringa. Per inviare informazioni di errore complesse dal server al client, usare la gestione degli errori avanzata.
Generare errori del server
Una chiamata al server gRPC restituisce sempre uno stato. Il server restituisce OK
automaticamente quando un metodo viene completato correttamente.
public class GreeterService : GreeterBase
{
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply { Message = $"Hello {request.Name}" });
}
public override async Task SayHelloStreaming(HelloRequest request,
IServerStreamWriter<HelloReply> responseStream, ServerCallContext context)
{
for (var i = 0; i < 5; i++)
{
await responseStream.WriteAsync(new HelloReply { Message = $"Hello {request.Name} {i}" });
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
}
Il codice precedente:
- Implementa il metodo unario
SayHello
che viene completato correttamente quando restituisce un messaggio di risposta. - Implementa il metodo di streaming
SayHelloStreaming
del server che viene completato correttamente al termine del metodo .
Stato dell'errore del server
I metodi gRPC restituiscono un codice di stato di errore generando un'eccezione. Quando viene generata un'eccezione RpcException
nel server, il codice di stato e la descrizione vengono restituiti al client:
public class GreeterService : GreeterBase
{
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
if (string.IsNullOrEmpty(request.Name))
{
throw new RpcException(new Status(StatusCode.InvalidArgument, "Name is required."));
}
return Task.FromResult(new HelloReply { Message = $"Hello {request.Name}" });
}
}
I tipi di eccezione generati non RpcException
causano anche l'esito negativo della chiamata, ma con un UNKNOWN
codice di stato e un messaggio generico Exception was thrown by handler
.
Exception was thrown by handler
viene inviato al client anziché al messaggio di eccezione per impedire l'esposizione di informazioni potenzialmente riservate. Per visualizzare un messaggio di errore più descrittivo in un ambiente di sviluppo, configurare EnableDetailedErrors
.
Gestire gli errori del client
Quando un client gRPC effettua una chiamata, il codice di stato viene convalidato automaticamente quando si accede alla risposta. Ad esempio, in attesa di una chiamata gRPC unaria restituisce il messaggio inviato dal server se la chiamata ha esito positivo e genera un'eccezione RpcException
in caso di errore. Intercettare RpcException
per gestire gli errori in un client:
var client = new Greet.GreeterClient(channel);
try
{
var response = await client.SayHelloAsync(new HelloRequest { Name = "World" });
Console.WriteLine("Greeting: " + response.Message);
}
catch (RpcException ex)
{
Console.WriteLine("Status code: " + ex.Status.StatusCode);
Console.WriteLine("Message: " + ex.Status.Detail);
}
Il codice precedente:
- Effettua una chiamata gRPC unaria al
SayHello
metodo . - Scrive il messaggio di risposta nella console se ha esito positivo.
RpcException
Rileva e scrive i dettagli dell'errore in caso di errore.
Scenari di errore
Gli errori sono rappresentati da RpcException
con un codice di stato di errore e un messaggio di dettaglio facoltativo. RpcException
viene generata in molti scenari:
- La chiamata non è riuscita nel server e il server ha inviato un codice di stato di errore. Ad esempio, il client gRPC ha avviato una chiamata senza dati necessari dal messaggio di richiesta e il server restituisce un
INVALID_ARGUMENT
codice di stato. - Si è verificato un errore all'interno del client durante l'esecuzione della chiamata gRPC. Ad esempio, un client effettua una chiamata gRPC, non può connettersi al server e genera un errore con lo stato
UNAVAILABLE
. - L'oggetto CancellationToken passato alla chiamata gRPC viene annullato. La chiamata gRPC viene arrestata e il client genera un errore con stato
CANCELLED
. - Una chiamata gRPC supera la scadenza configurata. La chiamata gRPC viene arrestata e il client genera un errore con stato
DEADLINE_EXCEEDED
.
Gestione degli errori avanzata
La gestione avanzata degli errori consente l'invio di informazioni complesse e strutturate con messaggi di errore. Ad esempio, la convalida dei campi messaggio in arrivo che restituisce un elenco di nomi di campo e descrizioni non validi. Il google.rpc.Status
modello di errore viene spesso usato per inviare informazioni di errore complesse tra app gRPC.
gRPC in .NET supporta un modello di errore avanzato usando il Grpc.StatusProto
pacchetto. Questo pacchetto include metodi per la creazione di modelli di errore avanzati nel server e la lettura da parte di un client. Il modello di errore avanzato si basa sulle funzionalità di gestione predefinite di gRPC e possono essere usate side-by-side.
Importante
Gli errori sono inclusi nelle intestazioni e le intestazioni totali nelle risposte sono spesso limitate a 8 KB (8.192 byte). Assicurarsi che le intestazioni contenenti errori non superino 8 KB.
Creazione di errori avanzati nel server
Gli errori avanzati vengono creati da Google.Rpc.Status
. Questo tipo è diverso da Grpc.Core.Status
.
Google.Rpc.Status
include campi di stato, messaggio e dettagli. Il campo più importante è costituito dai dettagli, ovvero un campo ripetuto di Any
valori. I dettagli sono la posizione in cui vengono aggiunti payload complessi.
Anche se qualsiasi tipo di messaggio può essere usato come payload, è consigliabile usare uno dei payload di errore standard:
BadRequest
PreconditionFailure
ErrorInfo
ResourceInfo
QuotaFailure
Grpc.StatusProto
include il ToRpcException
metodo helper da convertire Google.Rpc.Status
in un errore. Generare l'errore dal metodo del server gRPC:
public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
ArgumentNotNullOrEmpty(request.Name);
return Task.FromResult(new HelloReply { Message = "Hello " + request.Name });
}
public static void ArgumentNotNullOrEmpty(string value, [CallerArgumentExpression(nameof(value))] string? paramName = null)
{
if (string.IsNullOrEmpty(value))
{
var status = new Google.Rpc.Status
{
Code = (int)Code.InvalidArgument,
Message = "Bad request",
Details =
{
Any.Pack(new BadRequest
{
FieldViolations =
{
new BadRequest.Types.FieldViolation { Field = paramName, Description = "Value is null or empty" }
}
})
}
};
throw status.ToRpcException();
}
}
}
Lettura di errori avanzati da parte di un client
Gli errori avanzati vengono letti dal RpcException
rilevato nel client. Intercettare l'eccezione e usare i metodi helper forniti da Grpc.StatusCode
per ottenere la relativa Google.Rpc.Status
istanza:
var client = new Greet.GreeterClient(channel);
try
{
var reply = await client.SayHelloAsync(new HelloRequest { Name = name });
Console.WriteLine("Greeting: " + reply.Message);
}
catch (RpcException ex)
{
Console.WriteLine($"Server error: {ex.Status.Detail}");
var badRequest = ex.GetRpcStatus()?.GetDetail<BadRequest>();
if (badRequest != null)
{
foreach (var fieldViolation in badRequest.FieldViolations)
{
Console.WriteLine($"Field: {fieldViolation.Field}");
Console.WriteLine($"Description: {fieldViolation.Description}");
}
}
}
Il codice precedente:
- Effettua una chiamata gRPC all'interno di un try/catch che intercetta
RpcException
. - Chiama
GetRpcStatus()
per tentare di ottenere il modello di errore avanzato dall'eccezione. - Chiama
GetDetail<BadRequest>()
per tentare di ottenere unBadRequest
payload dall'errore avanzato.