Zpracování chyb pomocí gRPC
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Autor: James Newton-King
Tento článek popisuje zpracování chyb a gRPC:
- Integrované možnosti zpracování chyb pomocí stavových kódů gRPC a chybových zpráv
- Odesílání složitých strukturovaných informací o chybách pomocí bohatého zpracování chyb
Integrované zpracování chyb
Volání gRPC komunikují úspěch nebo selhání se stavovým kódem. Po úspěšném dokončení volání gRPC server vrátí OK
klientovi stav. Pokud dojde k chybě, vrátí gRPC:
- Stavový kód chyby, například
CANCELLED
neboUNAVAILABLE
. - Volitelná chybová zpráva řetězce.
Typy běžně používané při zpracování chyb:
StatusCode
: Výčet stavových kódů gRPC.OK
signály úspěchu; jiné hodnoty jsou neúspěšné.Status
: Astruct
, která kombinuje chybovouStatusCode
zprávu s volitelným řetězcem. Chybová zpráva obsahuje další podrobnosti o tom, co se stalo.RpcException
: Typ výjimky, který máStatus
hodnotu. Tato výjimka je vyvolána v metodách serveru gRPC a zachycena klienty gRPC.
Integrované zpracování chyb podporuje pouze stavový kód a popis řetězce. Chcete-li odeslat komplexní informace o chybách ze serveru klientovi, použijte bohaté zpracování chyb.
Vyvolání chyb serveru
Volání serveru gRPC vždy vrátí stav. Server se po úspěšném dokončení metody automaticky vrátí OK
.
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));
}
}
}
Předchozí kód:
- Implementuje unární
SayHello
metodu, která se úspěšně dokončí, když vrátí zprávu odpovědi. - Implementuje metodu streamování
SayHelloStreaming
serveru, která se po dokončení metody úspěšně dokončí.
Stav chyby serveru
Metody gRPC vrací stavový kód chyby vyvoláním výjimky. RpcException
Při vyvolání na serveru se klientovi vrátí jeho stavový kód a popis:
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}" });
}
}
Vyvolání typů výjimek, které také nezpůsobují RpcException
selhání volání, ale se stavovým UNKNOWN
kódem a obecnou zprávou Exception was thrown by handler
.
Exception was thrown by handler
je odeslán klientovi místo zprávy o výjimce, aby se zabránilo zveřejnění potenciálně citlivých informací. Pokud chcete zobrazit popisnější chybovou zprávu ve vývojovém prostředí, nakonfigurujte EnableDetailedErrors
.
Zpracování chyb klienta
Když klient gRPC zavolá, stavový kód se při přístupu k odpovědi automaticky ověří. Například čekání na unární volání gRPC vrátí zprávu poslanou serverem, pokud je volání úspěšné, a vyvolá RpcException
chybu, pokud dojde k selhání. Zachycení RpcException
pro zpracování chyb v klientovi:
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);
}
Předchozí kód:
- Provede volání unárního gRPC metody
SayHello
. - Pokud je zpráva odpovědi úspěšná, zapíše zprávu do konzoly.
- Zachytává
RpcException
a zapisuje podrobnosti o chybě při selhání.
Chybové scénáře
Chyby jsou reprezentovány kódem RpcException
stavu chyby a volitelnou podrobnou zprávou. RpcException
je vyvolán v mnoha scénářích:
- Volání se nezdařilo na serveru a server odeslal stavový kód chyby. Klient gRPC například spustil volání, které ve zprávě požadavku chybělo požadovaná data, a server vrátí stavový
INVALID_ARGUMENT
kód. - Při volání gRPC došlo v klientovi k chybě. Klient například provede volání gRPC, nemůže se připojit k serveru a vyvolá chybu se stavem
UNAVAILABLE
. - Volání CancellationToken gRPC se zruší. Volání gRPC je zastaveno a klient vyvolá chybu se stavem
CANCELLED
. - Volání gRPC překračuje nakonfigurovaný konečný termín. Volání gRPC je zastaveno a klient vyvolá chybu se stavem
DEADLINE_EXCEEDED
.
Zpracování bohatých chyb
Bohaté zpracování chyb umožňuje odesílání složitých strukturovaných informací s chybovými zprávami. Například ověření polí příchozích zpráv, která vrací seznam neplatných názvů polí a popisů. Model google.rpc.Status
chyby se často používá k odesílání složitých informací o chybách mezi aplikacemi gRPC.
GRPC v .NET podporuje bohatý chybový model pomocí Grpc.StatusProto
balíčku. Tento balíček obsahuje metody pro vytváření bohatých modelů chyb na serveru a jejich čtení klientem. Bohatý model chyb vychází z integrovaných možností zpracování gRPC a dá se použít vedle sebe.
Důležité
Chyby jsou zahrnuty do hlaviček a celkové hlavičky v odpovědích jsou často omezené na 8 kB (8 192 bajtů). Ujistěte se, že hlavičky obsahující chyby nepřekračují 8 kB.
Vytváření bohatých chyb na serveru
Bohaté chyby jsou vytvořeny z Google.Rpc.Status
. Tento typ se liší od Grpc.Core.Status
.
Google.Rpc.Status
obsahuje pole stavu, zprávy a podrobností. Nejdůležitější pole je podrobnosti, což je opakující se pole Any
hodnot. Podrobnosti jsou místa, kde se přidávají komplexní datové části.
I když se jako datovou část dá použít libovolný typ zprávy, doporučuje se použít jednu ze standardních datových částí chyb:
BadRequest
PreconditionFailure
ErrorInfo
ResourceInfo
QuotaFailure
Grpc.StatusProto
obsahuje pomocnou metodu ToRpcException
pro převod Google.Rpc.Status
na chybu. Vyvolá chybu z metody serveru 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();
}
}
}
Čtení bohatých chyb klientem
Bohaté chyby se čtou RpcException
z zachycených v klientovi. Zachyťte výjimku a použijte pomocné metody poskytované Grpc.StatusCode
k získání jeho Google.Rpc.Status
instance:
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}");
}
}
}
Předchozí kód:
- Provede volání gRPC uvnitř try/catch, který zachytí
RpcException
. - Volání
GetRpcStatus()
, která se pokusí z výjimky získat bohatý chybový model. - Volání
GetDetail<BadRequest>()
, která se pokusí získat datovouBadRequest
část z bohaté chyby.