Udostępnij za pośrednictwem


Obsługa błędów przy użyciu usługi gRPC

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.

Ważne

Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.

Autor: James Newton-King

W tym artykule omówiono obsługę błędów i gRPC:

  • Wbudowane możliwości obsługi błędów przy użyciu kodów stanu gRPC i komunikatów o błędach.
  • Wysyłanie złożonych, ustrukturyzowanych informacji o błędach przy użyciu rozbudowanej obsługi błędów.

Wbudowana obsługa błędów

Wywołania gRPC komunikują powodzenie lub niepowodzenie z kodem stanu. Po pomyślnym zakończeniu wywołania gRPC serwer zwraca OK stan do klienta. Jeśli wystąpi błąd, funkcja gRPC zwraca:

  • Kod stanu błędu, taki jak CANCELLED lub UNAVAILABLE.
  • Opcjonalny komunikat o błędzie ciągu.

Typy często używane z obsługą błędów to:

  • StatusCode: wyliczenie kodów stanu gRPC. OK sygnalizuje powodzenie; inne wartości to niepowodzenie.
  • Status: Element struct , który łączy StatusCode opcjonalny komunikat o błędzie ciągu. Komunikat o błędzie zawiera dodatkowe szczegóły dotyczące tego, co się stało.
  • RpcException: typ wyjątku, który ma Status wartość. Ten wyjątek jest zgłaszany w metodach serwera gRPC i przechwycony przez klientów gRPC.

Wbudowana obsługa błędów obsługuje tylko kod stanu i opis ciągu. Aby wysyłać złożone informacje o błędach z serwera do klienta, użyj rozbudowanej obsługi błędów.

Zgłaszanie błędów serwera

Wywołanie serwera gRPC zawsze zwraca stan. Serwer jest automatycznie zwracany OK po pomyślnym zakończeniu metody.

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));
        }
    }
}

Powyższy kod ma następujące działanie:

  • Implementuje jednoargumentową SayHello metodę, która kończy się pomyślnie po zwracaniu komunikatu odpowiedzi.
  • Implementuje metodę przesyłania strumieniowego SayHelloStreaming serwera, która kończy się pomyślnie po zakończeniu metody.

Stan błędu serwera

Metody gRPC zwracają kod stanu błędu, zgłaszając wyjątek. Gdy obiekt RpcException zostanie zgłoszony na serwerze, jego kod stanu i opis są zwracane do klienta:

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}" });
    }
}

Zgłaszane typy wyjątków, które nie RpcException powodują również niepowodzenia wywołania, ale z UNKNOWN kodem stanu i ogólnym komunikatem Exception was thrown by handler.

Exception was thrown by handler program jest wysyłany do klienta, a nie do komunikatu o wyjątku, aby zapobiec ujawnieniu potencjalnie poufnych informacji. Aby wyświetlić bardziej opisowy komunikat o błędzie w środowisku projektowym, skonfiguruj element EnableDetailedErrors.

Obsługa błędów klienta

Gdy klient gRPC wykonuje wywołanie, kod stanu jest automatycznie weryfikowany podczas uzyskiwania dostępu do odpowiedzi. Na przykład oczekiwanie na jednoargumentowe wywołanie gRPC zwraca komunikat wysyłany przez serwer, jeśli wywołanie powiedzie się i zgłasza błąd RpcException . Przechwyć RpcException w celu obsługi błędów w kliencie:

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);
}

Powyższy kod ma następujące działanie:

  • Wykonuje jednoargumentowe wywołanie gRPC do SayHello metody .
  • Zapisuje komunikat odpowiedzi w konsoli, jeśli zakończy się pomyślnie.
  • Przechwytuje RpcException i zapisuje szczegóły błędu dotyczące błędu.

Scenariusze błędów

Błędy są reprezentowane przez RpcException kod stanu błędu i opcjonalny komunikat szczegółów. RpcException jest zgłaszany w wielu scenariuszach:

  • Wywołanie nie powiodło się na serwerze, a serwer wysłał kod stanu błędu. Na przykład klient gRPC uruchomił wywołanie, które nie zawiera wymaganych danych z komunikatu żądania, a serwer zwraca INVALID_ARGUMENT kod stanu.
  • Wystąpił błąd wewnątrz klienta podczas wykonywania wywołania gRPC. Na przykład klient wykonuje wywołanie gRPC, nie może nawiązać połączenia z serwerem i zgłasza błąd ze stanem UNAVAILABLE.
  • Przekazana CancellationToken do wywołania gRPC jest anulowana. Wywołanie gRPC zostało zatrzymane, a klient zgłasza błąd ze stanem CANCELLED.
  • Wywołanie gRPC przekracza skonfigurowany termin. Wywołanie gRPC zostało zatrzymane, a klient zgłasza błąd ze stanem DEADLINE_EXCEEDED.

Zaawansowana obsługa błędów

Zaawansowana obsługa błędów umożliwia wysyłanie złożonych, ustrukturyzowanych informacji z komunikatami o błędach. Na przykład weryfikacja przychodzących pól komunikatów, które zwracają listę nieprawidłowych nazw pól i opisów. google.rpc.Status Model błędów jest często używany do wysyłania złożonych informacji o błędach między aplikacjami gRPC.

Usługa gRPC na platformie .NET obsługuje zaawansowany model błędów przy użyciu Grpc.StatusProto pakietu. Ten pakiet zawiera metody tworzenia zaawansowanych modeli błędów na serwerze i odczytywania ich przez klienta. Bogaty model błędów opiera się na wbudowanych możliwościach obsługi gRPC i mogą być używane obok siebie.

Ważne

Błędy są uwzględniane w nagłówkach, a łączna liczba nagłówków w odpowiedziach jest często ograniczona do 8 KB (8192 bajtów). Upewnij się, że nagłówki zawierające błędy nie przekraczają 8 KB.

Tworzenie rozbudowanych błędów na serwerze

Rozbudowane błędy są tworzone na podstawie Google.Rpc.Statuselementu . Ten typ różni się od .Grpc.Core.Status

Google.Rpc.Status zawiera pola stanu, komunikatu i szczegółów. Najważniejsze pole to szczegóły, czyli powtarzające się pole Any wartości. Szczegóły to miejsce, w którym dodawane są złożone ładunki.

Mimo że dowolny typ komunikatu może być używany jako ładunek, zaleca się użycie jednego ze standardowych ładunków błędów:

  • BadRequest
  • PreconditionFailure
  • ErrorInfo
  • ResourceInfo
  • QuotaFailure

Grpc.StatusProtoToRpcException zawiera metodę pomocnika, która ma być konwertowana Google.Rpc.Status na błąd. Wyrzuć błąd z metody serwera 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();
        }
    }
}

Odczytywanie rozbudowanych błędów przez klienta

Rozbudowane błędy są odczytywane z przechwyconego RpcException w kliencie. Przechwyć wyjątek i użyj metod pomocnika udostępnianych przez Grpc.StatusCode program , aby uzyskać jego Google.Rpc.Status wystąpienie:

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}");
        }
    }
}

Powyższy kod ma następujące działanie:

  • Wykonuje wywołanie gRPC wewnątrz try/catch, które przechwytuje RpcException.
  • Wywołuje GetRpcStatus() metodę próby pobrania zaawansowanego modelu błędów z wyjątku.
  • Wywołania GetDetail<BadRequest>() próby pobrania BadRequest ładunku z zaawansowanego błędu.

Dodatkowe zasoby