Obsługa błędów przejściowych przy użyciu ponownych prób 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.
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
Ponowne próby usługi gRPC to funkcja umożliwiająca klientom gRPC automatyczne ponawianie nieudanych wywołań. W tym artykule omówiono sposób konfigurowania zasad ponawiania w celu tworzenia odpornych, odpornych na błędy aplikacji gRPC na platformie .NET.
Ponowne próby usługi gRPC wymagają klienta Grpc.Net.Client w wersji 2.36.0 lub nowszej.
Obsługa błędu przejściowego
Wywołania gRPC mogą zostać przerwane przez błędy przejściowe. Błędy przejściowe obejmują:
- Chwilowa utrata łączności sieciowej.
- Tymczasowa niedostępność usługi.
- Przekroczenia limitu czasu z powodu obciążenia serwera.
Gdy wywołanie gRPC zostanie przerwane, klient zgłasza komunikat RpcException
ze szczegółowymi informacjami o błędzie. Aplikacja kliencka musi przechwycić wyjątek i wybrać sposób obsługi błędu.
var client = new Greeter.GreeterClient(channel);
try
{
var response = await client.SayHelloAsync(
new HelloRequest { Name = ".NET" });
Console.WriteLine("From server: " + response.Message);
}
catch (RpcException ex)
{
// Write logic to inspect the error and retry
// if the error is from a transient fault.
}
Duplikowanie logiki ponawiania prób w całej aplikacji jest pełne i podatne na błędy. Na szczęście klient gRPC platformy .NET ma wbudowaną obsługę automatycznych ponownych prób.
Konfigurowanie zasad ponawiania prób usługi gRPC
Zasady ponawiania są konfigurowane raz po utworzeniu kanału gRPC:
var defaultMethodConfig = new MethodConfig
{
Names = { MethodName.Default },
RetryPolicy = new RetryPolicy
{
MaxAttempts = 5,
InitialBackoff = TimeSpan.FromSeconds(1),
MaxBackoff = TimeSpan.FromSeconds(5),
BackoffMultiplier = 1.5,
RetryableStatusCodes = { StatusCode.Unavailable }
}
};
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
});
Powyższy kod ma następujące działanie:
- Tworzy element
MethodConfig
. Zasady ponawiania można skonfigurować dla metody i metody są dopasowywane przy użyciuNames
właściwości . Ta metoda jest skonfigurowana za pomocąMethodName.Default
metody , więc jest stosowana do wszystkich metod gRPC wywoływanych przez ten kanał. - Konfiguruje zasady ponawiania prób. Te zasady instruują klientów, aby automatycznie ponawiali próby wywołań gRPC, które kończą się niepowodzeniem z kodem
Unavailable
stanu . - Konfiguruje utworzony kanał tak, aby używał zasad ponawiania przez ustawienie .
GrpcChannelOptions.ServiceConfig
Klienci gRPC utworzone za pomocą kanału będą automatycznie ponawiać nieudane wywołania:
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
new HelloRequest { Name = ".NET" });
Console.WriteLine("From server: " + response.Message);
Gdy ponawianie prób jest prawidłowe
Wywołania są ponawiane, gdy:
- Kod stanu niepowodzenia jest zgodny z wartością w pliku
RetryableStatusCodes
. - Poprzednia liczba prób jest mniejsza niż
MaxAttempts
. - Połączenie nie zostało zatwierdzone.
- Termin nie został przekroczony.
Wywołanie gRPC zostaje zatwierdzone w dwóch scenariuszach:
- Klient otrzymuje nagłówki odpowiedzi. Nagłówki odpowiedzi są wysyłane przez serwer po
ServerCallContext.WriteResponseHeadersAsync
wywołaniu lub gdy pierwszy komunikat jest zapisywany do strumienia odpowiedzi serwera. - Komunikat wychodzący klienta (lub komunikaty w przypadku przesyłania strumieniowego) przekroczył maksymalny rozmiar buforu klienta.
MaxRetryBufferSize
iMaxRetryBufferPerCallSize
są skonfigurowane w kanale.
Zatwierdzone wywołania nie będą ponawiane, niezależnie od kodu stanu lub poprzedniej liczby prób.
Połączenia przesyłane strumieniowo
Wywołania przesyłania strumieniowego mogą być używane z ponownymi próbami gRPC, ale ważne są istotne kwestie, gdy są używane razem:
- Przesyłanie strumieniowe serwera, przesyłanie strumieniowe dwukierunkowe: przesyłania strumieniowego żądań przesyłania strumieniowego, które zwracają wiele komunikatów z serwera, nie będą ponawiane po odebraniu pierwszego komunikatu. Aplikacje muszą dodać dodatkową logikę, aby ręcznie ponownie ustanowić serwer i dwukierunkowe wywołania przesyłania strumieniowego.
- Przesyłanie strumieniowe klienta, przesyłanie strumieniowe dwukierunkowe: przesyłania strumieniowego żądań przesyłania strumieniowego, które wysyłają wiele komunikatów do serwera, nie będą ponawiane próby, jeśli komunikaty wychodzące przekroczyły maksymalny rozmiar buforu klienta. Maksymalny rozmiar buforu można zwiększyć przy użyciu konfiguracji.
Aby uzyskać więcej informacji, zobacz Kiedy ponowne próby są prawidłowe.
Opóźnienie ponawiania próby wycofywania
Opóźnienie wycofywania między ponownymi próbami jest skonfigurowane za pomocą poleceń InitialBackoff
, MaxBackoff
i BackoffMultiplier
. Więcej informacji o każdej opcji jest dostępnych w sekcji opcje ponawiania prób gRPC.
Rzeczywiste opóźnienie między próbami ponawiania jest losowe. Losowe opóźnienie z zakresu od 0 do bieżącego wycofywania określa, kiedy zostanie podjęta kolejna ponowna próba. Należy wziąć pod uwagę, że nawet w przypadku skonfigurowania wycofywania wykładniczego zwiększenie bieżącego wycofywania między próbami rzeczywiste opóźnienie między próbami nie zawsze jest większe. Opóźnienie jest losowe, aby zapobiec ponawianiu prób z wielu wywołań ze sobą klastrowania i potencjalnie przeciążenia serwera.
Wykrywanie ponownych prób za pomocą metadanych
Ponawianie prób przez gRPC może być wykrywane przez obecność metadanych grpc-previous-rpc-attempts
. Metadane grpc-previous-rpc-attempts
:
- Jest automatycznie dodawany do ponawianych wywołań i wysyłany do serwera.
- Wartość reprezentuje liczbę poprzednich ponownych prób.
- Wartość jest zawsze liczbą całkowitą.
Rozważmy następujący scenariusz ponawiania prób:
- Klient wykonuje wywołanie gRPC do serwera.
- Serwer kończy się niepowodzeniem i zwraca ponowną odpowiedź kodu stanu.
- Klient ponawia próbę wywołania gRPC. Ponieważ była jedna poprzednia próba,
grpc-previous-rpc-attempts
metadane mają wartość1
. Metadane są wysyłane do serwera przy użyciu ponawiania. - Serwer kończy się powodzeniem i zwraca wartość OK.
- Klient zgłasza powodzenie.
grpc-previous-rpc-attempts
znajduje się w metadanych odpowiedzi i ma wartość1
.
Metadane grpc-previous-rpc-attempts
nie są obecne w początkowym wywołaniu gRPC, jest 1
dla pierwszego ponawiania, 2
dla drugiego ponawiania i tak dalej.
Opcje ponawiania prób gRPC
W poniższej tabeli opisano opcje konfigurowania zasad ponawiania prób gRPC:
Opcja | Opis |
---|---|
MaxAttempts |
Maksymalna liczba prób wywołania, w tym oryginalna próba. Ta wartość jest ograniczona GrpcChannelOptions.MaxRetryAttempts domyślnie do 5. Wymagana jest wartość i musi być większa niż 1. |
InitialBackoff |
Początkowe opóźnienie wycofywania między próbami ponawiania prób. Losowe opóźnienie z zakresu od 0 do bieżącego wycofywania określa, kiedy zostanie podjęta kolejna ponowna próba. Po każdej próbie bieżące wycofywanie jest mnożone przez BackoffMultiplier element . Wymagana jest wartość i musi być większa niż zero. |
MaxBackoff |
Maksymalne wycofywanie powoduje górny limit wzrostu wycofywania wykładniczego. Wymagana jest wartość i musi być większa niż zero. |
BackoffMultiplier |
Wycofywanie zostanie pomnożone przez tę wartość po każdej próbie ponawiania próby i zwiększy wykładniczo, gdy mnożnik jest większy niż 1. Wymagana jest wartość i musi być większa niż zero. |
RetryableStatusCodes |
Kolekcja kodów stanu. Wywołanie gRPC, które kończy się niepowodzeniem z pasującym stanem, zostanie automatycznie ponowione. Aby uzyskać więcej informacji na temat kodów stanu, zobacz Kody stanu i ich użycie w gRPC. Wymagany jest co najmniej jeden kod stanu, który można ponowić. |
Zabezpieczenia
Zabezpieczanie jest alternatywną strategią ponawiania prób. Zabezpieczenie umożliwia agresywne wysyłanie wielu kopii pojedynczego wywołania gRPC bez oczekiwania na odpowiedź. Wywołania gRPC zabezpieczeń mogą być wykonywane wiele razy na serwerze i jest używany pierwszy pomyślny wynik. Ważne jest, aby zabezpieczenie było włączone tylko dla metod, które są bezpieczne do wykonania wiele razy bez negatywnego wpływu.
Hedging ma zalety i wady w porównaniu do ponownych prób:
- Zaletą zabezpieczenia jest to, że może zwrócić udany wynik szybciej. Umożliwia to wiele jednoczesnych wywołań gRPC i zostanie ukończonych po udostępnieniu pierwszego pomyślnego wyniku.
- Wadą zabezpieczenia jest to, że może to być marne. Można wykonać wiele wywołań i wszystkie zakończyły się powodzeniem. Używany jest tylko pierwszy wynik i rest są odrzucane.
Konfigurowanie zasad zabezpieczania gRPC
Zasady zabezpieczania są konfigurowane jak zasady ponawiania prób. Należy pamiętać, że zasady zabezpieczania nie mogą być łączone z zasadami ponawiania prób.
var defaultMethodConfig = new MethodConfig
{
Names = { MethodName.Default },
HedgingPolicy = new HedgingPolicy
{
MaxAttempts = 5,
NonFatalStatusCodes = { StatusCode.Unavailable }
}
};
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
});
Opcje zabezpieczania gRPC
W poniższej tabeli opisano opcje konfigurowania zasad zabezpieczeń gRPC:
Opcja | Opis |
---|---|
MaxAttempts |
Polityka zabezpieczania wyśle do tej liczby połączeń. MaxAttempts reprezentuje łączną liczbę wszystkich prób, w tym oryginalną próbę. Ta wartość jest ograniczona GrpcChannelOptions.MaxRetryAttempts domyślnie do 5. Wymagana jest wartość i musi być 2 lub większa. |
HedgingDelay |
Pierwsze wywołanie jest wysyłane natychmiast, kolejne wywołania zabezpieczające są opóźnione przez tę wartość. Gdy opóźnienie jest ustawione na zero lub null , wszystkie wywołania zabezpieczone są wysyłane natychmiast. HedgingDelay parametr jest opcjonalny, a wartością domyślną jest zero. Wartość musi być równa zero lub większa. |
NonFatalStatusCodes |
Kolekcja kodów stanu, które wskazują inne wywołania hedgingowe, mogą nadal zakończyć się powodzeniem. Jeśli serwer zwraca kod stanu niekrytyczny, wywołania zabezpieczone będą kontynuowane. W przeciwnym razie zaległe żądania zostaną anulowane i zostanie zwrócony błąd do aplikacji. Aby uzyskać więcej informacji na temat kodów stanu, zobacz Kody stanu i ich użycie w gRPC. |