Gestion des erreurs avec gRPC
Remarque
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 9 de cet article.
Avertissement
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la stratégie de support .NET et .NET Core. Pour la version actuelle, consultez la version .NET 9 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 9 de cet article.
Cet article traite de la gestion des erreurs et de gRPC :
- Fonctionnalités intégrées de gestion des erreurs à l’aide des codes d’état et des messages d’erreur gRPC
- Envoi d’informations complexes et structurées sur les erreurs à l’aide d’une gestion complète des erreurs
Gestion des erreurs intégrée
Les appels gRPC communiquent la réussite ou l’échec avec un code d’état. Lorsqu’un appel gRPC se termine correctement, le serveur retourne un état OK
au client. Si une erreur se produit, gRPC retourne :
- Un code d’état d’erreur, tel que
CANCELLED
ouUNAVAILABLE
- Un message d’erreur de chaîne facultatif
Les types couramment utilisés avec la gestion des erreurs sont les suivants :
StatusCode
: énumération des codes d’état gRPC.OK
indique la réussite, tandis que les autres valeurs sont des échecs.Status
: unestruct
qui combine unStatusCode
et un message d’erreur de chaîne facultatif. Le message d’erreur fournit des détails supplémentaires sur ce qui s’est passé.RpcException
: type d’exception pourvu de la valeurStatus
. Cette exception est levée dans les méthodes serveur gRPC et interceptée par les clients gRPC.
La gestion des erreurs intégrée prend uniquement en charge un code d’état et une description de chaîne. Pour envoyer des informations sur des erreurs complexes du serveur au client, utilisez une gestion complète des erreurs.
Levée d’erreurs de serveur
Un appel de serveur gRPC retourne toujours un état. Le serveur retourne automatiquement OK
lorsqu’une méthode se termine correctement.
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));
}
}
}
Le code précédent :
- Implémente la méthode
SayHello
unaire qui se termine correctement lorsqu’elle retourne un message de réponse. - Implémente la méthode
SayHelloStreaming
de diffusion en continu du serveur qui se termine correctement une fois la méthode terminée.
État d’erreur du serveur
Les méthodes gRPC retournent un code d’état d’erreur en levant une exception. Lorsqu’une RpcException
est levée sur le serveur, son code d’état et sa description sont retournés au 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}" });
}
}
Les types d’exceptions levées qui ne sont pas RpcException
provoquent également l’échec de l’appel, mais avec un code d’état UNKNOWN
et un message générique Exception was thrown by handler
.
Exception was thrown by handler
est envoyé au client plutôt que le message d’exception pour empêcher l’exposition d’informations potentiellement sensibles. Pour afficher un message d’erreur plus descriptif dans un environnement de développement, configurez EnableDetailedErrors
.
Gestion des erreurs de client
Lorsqu’un client gRPC effectue un appel, le code d’état est automatiquement validé lors de l’accès à la réponse. Par exemple, l’attente d’un appel gRPC unaire retourne le message envoyé par le serveur si l’appel aboutit et lève une RpcException
en cas d’échec. Interceptez RpcException
pour gérer les erreurs d’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);
}
Le code précédent :
- Effectue un appel gRPC unaire vers la méthode
SayHello
. - Écrit le message de réponse dans la console en cas de réussite.
- Intercepte
RpcException
et écrit les détails de l’erreur en cas d’échec.
Scénarios d’erreur
Les erreurs sont représentées par RpcException
avec un code d’état d’erreur et un message de détail facultatif. RpcException
est levée dans de nombreux scénarios :
- L’appel a échoué sur le serveur, qui a envoyé un code d’état d’erreur. Par exemple, le client gRPC a démarré un appel auquel des données requises manquaient à partir du message de demande et le serveur retourne un code d’état
INVALID_ARGUMENT
. - Une erreur s’est produite à l’intérieur du client lors de l’appel gRPC. Par exemple, un client effectue un appel gRPC, ne peut pas se connecter au serveur et génère une erreur avec l’état
UNAVAILABLE
. - Le CancellationToken transmis à l’appel gRPC est annulé. L’appel gRPC est arrêté et le client lève une erreur avec l’état
CANCELLED
. - Un appel gRPC dépasse l’échéance configurée. L’appel gRPC est arrêté et le client lève une erreur avec l’état
DEADLINE_EXCEEDED
.
Gestion complète des erreurs
La gestion complète des erreurs permet d’envoyer des informations complexes et structurées avec des messages d’erreur. Par exemple, la validation des champs de message entrants qui retourne une liste de noms et de descriptions de champs non valides. Le modèle d’erreur google.rpc.Status
est souvent utilisé pour envoyer des informations sur des erreurs complexes entre les applications gRPC.
gRPC sur .NET prend en charge un modèle d’erreur enrichi à l’aide du package Grpc.StatusProto
. Ce package comporte des méthodes pour créer des modèles d’erreur enrichis sur le serveur et les faire lire par un client. Le modèle d’erreur enrichi s’appuie sur les fonctionnalités de gestion intégrées de gRPC et peut être utilisé côte à côte.
Important
Les erreurs sont incluses dans les en-têtes, dont le total dans les réponses est souvent limité à 8 Ko (8 192 octets). Vérifiez que les en-têtes contenant des erreurs ne dépassent pas 8 Ko.
Création d’erreurs enrichies sur le serveur
Les erreurs enrichies sont créées à partir de Google.Rpc.Status
. Ce type est différent de Grpc.Core.Status
.
Google.Rpc.Status
contient des champs d’état, de message et de détails. Le champ le plus important est le champ de détails, qui est un champ répétitif des valeurs Any
. Les détails sont l’emplacement où des charges utiles complexes sont ajoutées.
Bien que tout type de message puisse être utilisé comme charge utile, il est recommandé d’utiliser l’une des charges utiles d’erreur standard :
BadRequest
PreconditionFailure
ErrorInfo
ResourceInfo
QuotaFailure
Grpc.StatusProto
inclut la ToRpcException
, une méthode d’assistance pour convertir Google.Rpc.Status
en erreur. Levez l’erreur à partir de la méthode de serveur 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();
}
}
}
Lecture d’erreurs enrichies par un client
Les erreurs enrichies sont lues à partir de la RpcException
interceptée dans le client. Interceptez l’exception et utilisez les méthodes d’assistance fournies par Grpc.StatusCode
pour obtenir son instance Google.Rpc.Status
:
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}");
}
}
}
Le code précédent :
- Effectue un appel gRPC à l’intérieur d’un try/catch qui intercepte
RpcException
. - Appelle
GetRpcStatus()
pour tenter d’obtenir le modèle d’erreur enrichi à partir de l’exception. - Appelle
GetDetail<BadRequest>()
pour tenter d’obtenir une charge utileBadRequest
à partir de l’erreur enrichie.