Behandlung vorübergehender Fehler mit gRPC-Wiederholungen
Hinweis
Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.
Warnung
Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der Supportrichtlinie für .NET und .NET Core. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.
Wichtig
Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.
Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.
Bei gRPC-Wiederholungen handelt es sich um ein Feature, mit dem gRPC-Clients Aufrufe, die zu einem Fehler geführt haben, automatisch wiederholen können. In diesem Artikel wird erläutert, wie Sie eine Wiederholungsrichtlinie konfigurieren, um robuste, fehlertolerante gRPC-Apps in .NET zu erstellen.
Für gRPC-Wiederholungen ist Version 2.36.0 oder höher von Grpc.Net.Client erforderlich.
Behandeln vorübergehender Fehler
gRPC-Aufrufe können durch vorübergehende Fehler unterbrochen werden. Vorübergehende Fehler sind z. B.:
- Vorübergehender Verlust der Netzwerkverbindung.
- Vorübergehende Nichtverfügbarkeit eines Diensts.
- Timeouts aufgrund der Serverauslastung.
Wenn ein gRPC-Aufruf unterbrochen wird, löst der Client eine RpcException
mit Details zum Fehler aus. Die Client-App muss die Ausnahme abfangen und bestimmen, wie der Fehler behandelt werden soll.
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.
}
Das Duplizieren der Wiederholungslogik in einer App wäre umständlich und fehleranfällig. Glücklicherweise verfügt der .NET-gRPC-Client über eine integrierte Unterstützung für automatische Wiederholungen.
Konfigurieren einer gRPC-Wiederholungsrichtlinie
Bei Erstellung eines gRPC-Kanals wird eine Wiederholungsrichtlinie konfiguriert:
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 } }
});
Der vorangehende Code:
- Erstellt eine
MethodConfig
. Wiederholungsrichtlinien können methodenweise konfiguriert werden, und die Methoden werden über dieNames
Eigenschaft zugeordnet. Diese Methode ist mitMethodName.Default
konfiguriert, sodass Sie auf alle von diesem Kanal aufgerufenen gRPC-Methoden angewendet wird. - Konfiguriert eine Wiederholungsrichtlinie. Diese Richtlinie weist Clients an, gRPC-Aufrufe, die zu einem Fehler mit dem Statuscode
Unavailable
führen, automatisch zu wiederholen. - Konfiguriert den erstellten Kanal für die Verwendung der Wiederholungsrichtlinie, indem
GrpcChannelOptions.ServiceConfig
festgelegt wird.
Mit dem Kanal erstellte gRPC-Clients führen bei Aufruffehlern automatisch Wiederholungsversuche durch:
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
new HelloRequest { Name = ".NET" });
Console.WriteLine("From server: " + response.Message);
Unter welchen Umständen Wiederholungsversuche gültig sind
Aufrufe werden wiederholt, wenn:
- Der Fehlerstatuscode einem Wert in
RetryableStatusCodes
entspricht. - Die vorherige Anzahl von Versuchen kleiner als
MaxAttempts
ist. - Der Aufruf nicht committet wurde.
- Die Frist nicht überschritten wurde.
Ein gRPC-Aufruf wird in zwei Szenarien committet:
- Der Client empfängt Antwortheader. Antwortheader werden vom Server gesendet, wenn
ServerCallContext.WriteResponseHeadersAsync
aufgerufen wird, oder wenn die erste Nachricht in den Serverantwortstream geschrieben wird. - Die ausgehende Nachricht des Clients (oder Nachrichten bei Streaming) hat die maximale Puffergröße des Clients überschritten.
MaxRetryBufferSize
undMaxRetryBufferPerCallSize
werden für den Kanal konfiguriert.
Committete Aufrufe werden nicht wiederholt, unabhängig vom Statuscode oder der vorherigen Anzahl von Versuchen.
Streamingaufrufe
Streamingaufrufe können mit gRPC-Wiederholungsversuchen verwendet werden, aber es gibt wichtige Überlegungen, wenn sie gemeinsam verwendet werden:
- Serverstreaming, bidirektionales Streaming: Streaming-RPCs, die mehrere Nachrichten vom Server zurückgeben, werden nicht wiederholt, nachdem die erste Nachricht empfangen wurde. Apps müssen zusätzliche Logik hinzufügen, um Server- und bidirektionale Streamingaufrufe manuell neu einzurichten.
- Clientstreaming, bidirektionales Streaming: Streaming-RPCs, die mehrere Nachrichten an den Server senden, werden nicht wiederholt, wenn die ausgehenden Nachrichten die maximale Puffergröße des Clients überschritten haben. Die maximale Puffergröße kann mittels Konfiguration erhöht werden.
Weitere Informationen finden Sie unter Unter welchen Umständen Wiederholungsversuche gültig sind.
Backoffverzögerung für Wiederholungen
Die Backoffverzögerung zwischen Wiederholungsversuchen wird mit InitialBackoff
, MaxBackoff
und BackoffMultiplier
konfiguriert. Weitere Informationen zu den einzelnen Optionen finden Sie im Abschnitt Optionen für gRPC-Wiederholungen.
Die tatsächliche Verzögerung zwischen Wiederholungsversuchen ist zufällig. Eine zufällige Verzögerung zwischen 0 und dem aktuellen Backoff bestimmt, wann der nächste Wiederholungsversuch unternommen wird. Beachten Sie, dass selbst bei einer Konfiguration von exponentiellen Backoffs, durch die der aktuelle Backoff zwischen Versuchen erhöht wird, die tatsächliche Verzögerung zwischen den Versuchen nicht immer größer ist. Die Verzögerung ist zufällig, um zu verhindern, dass Wiederholungen mehrerer Aufrufe zusammentreffen und der Server möglicherweise überlastet wird.
Erkennen von Wiederholungen mit Metadaten
gRPC-Wiederholungen können durch das Vorhandensein von Metadaten für grpc-previous-rpc-attempts
erkannt werden. Für Metadaten für grpc-previous-rpc-attempts
gilt Folgendes:
- Werden automatisch zu wiederholten Anrufen hinzugefügt und zum Server gesendet.
- Der Wert stellt die Anzahl der vorherigen Wiederholungsversuche dar.
- Der Wert ist stets eine ganze Zahl.
Betrachten Sie folgendes Wiederholungsszenario:
- Der Client richtet einen gRPC-Aufruf an den Server.
- Der Server meldet einen Fehler und gibt eine wiederholbare Statuscodeantwort zurück.
- Der Client wiederholt den gRPC-Aufruf. Da es bereits einen Versuch gab, haben die Metadaten für
grpc-previous-rpc-attempts
den Wert1
. Metadaten werden mit der Wiederholung zum Server gesendet. - Der Server meldet Erfolg und gibt OK zurück.
- Der Client meldet Erfolg.
grpc-previous-rpc-attempts
ist in den Metadaten der Antwort enthalten und hat den Wert1
.
Die Metadaten von grpc-previous-rpc-attempts
sind beim ersten gRPC-Aufruf nicht vorhanden, für den ersten Wiederholungsversuch 1
, für den zweiten Wiederholungsversuch 2
usw.
Optionen für gRPC-Wiederholungen
In der folgenden Tabelle werden die Optionen für die Konfiguration von gRPC-Wiederholungsrichtlinien beschrieben:
Option | Beschreibung |
---|---|
MaxAttempts |
Die maximale Anzahl von Aufrufversuchen, einschließlich des ursprünglichen Versuchs. Dieser Wert wird durch GrpcChannelOptions.MaxRetryAttempts mit dem Standardwert 5 begrenzt. Ein Wert ist erforderlich und muss größer als 1 sein. |
InitialBackoff |
Die anfängliche Backoffverzögerung zwischen Wiederholungsversuchen. Eine zufällige Verzögerung zwischen 0 und dem aktuellen Backoff bestimmt, wann der nächste Wiederholungsversuch unternommen wird. Nach jedem Versuch wird der aktuelle Backoff mit BackoffMultiplier multipliziert. Ein Wert ist erforderlich und muss größer als 0 sein. |
MaxBackoff |
Der maximale Backoff stellt eine Obergrenze für die exponentielle Backoffzunahme dar. Ein Wert ist erforderlich und muss größer als 0 sein. |
BackoffMultiplier |
Der Backoff wird nach jedem Wiederholungsversuch mit diesem Wert multipliziert und erhöht sich exponentiell, wenn der Multiplikator größer als 1 ist. Ein Wert ist erforderlich und muss größer als 0 sein. |
RetryableStatusCodes |
Eine Sammlung von Statuscodes. Ein gRPC-Aufruf, bei dem ein Fehler mit dem entsprechenden Status auftritt, wird automatisch wiederholt. Weitere Informationen zu Statuscodes finden Sie unter Statuscodes und deren Verwendung in gRPC. Mindestens ein Statuscode ist erforderlich, bei dem eine Wiederholung möglich ist. |
Hedging
Das Hedging stellt eine alternative Wiederholungsstrategie dar. Das Hedging ermöglicht das aggressive Senden mehrerer Kopien eines einzelnen gRPC-Aufrufs, ohne auf eine Antwort zu warten. gRPC-Hedgingaufrufe können mehrmals auf dem Server ausgeführt werden, und das erste erfolgreiche Ergebnis wird verwendet. Es ist wichtig, dass das Hedging nur für Methoden aktiviert wird, die ohne negative Auswirkungen mehrmals ausgeführt werden können.
Das Hedging hat gegenüber Wiederholungen Vor- und Nachteile:
- Ein Vorteil des Hedgings ist, dass ein erfolgreiches Ergebnis schneller zurückgegeben werden kann. Sie ermöglicht mehrere gleichzeitige gRPC-Aufrufe und wird beendet, wenn das erste erfolgreiche Ergebnis verfügbar ist.
- Ein Nachteil des Hedgings ist, dass es unnötig Ressourcen verbraucht. Es können mehrere Aufrufe durchgeführt werden, die alle erfolgreich sind. Es wird nur das erste Ergebnis verwendet, der Rest wird verworfen.
Konfigurieren einer gRPC-Hedgingrichtlinie
Eine Hedgingrichtlinie wird wie eine Wiederholungsrichtlinie konfiguriert. Beachten Sie, dass eine Hedgingrichtlinie nicht mit einer Wiederholungsrichtlinie kombiniert werden kann.
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 } }
});
Optionen für das gRPC-Hedging
In der folgenden Tabelle werden die Optionen für die Konfiguration von gRPC-Hedgingrichtlinien beschrieben:
Option | Beschreibung |
---|---|
MaxAttempts |
Die Höchstzahl von Aufrufen, die von der Hedgingrichtlinie gesendet werden. MaxAttempts stellt die Gesamtzahl aller Versuche dar, einschließlich des ursprünglichen Versuchs. Dieser Wert wird durch GrpcChannelOptions.MaxRetryAttempts mit dem Standardwert 5 begrenzt. Ein Wert ist erforderlich und muss mindestens 2 betragen. |
HedgingDelay |
Der erste Aufruf wird sofort gesendet, und die nachfolgenden Hedgingaufrufe werden um diesen Wert verzögert. Wenn die Verzögerung auf 0 oder null festgelegt ist, werden alle Hedgingaufrufe sofort gesendet. HedgingDelay ist optional und ist standardmäßig auf 0 (null) festgelegt. Ein Wert muss 0 (null) oder größer sein. |
NonFatalStatusCodes |
Eine Sammlung von Statuscodes, für die gilt, dass andere Hedgingaufrufe möglicherweise trotzdem erfolgreich ausgeführt werden. Wenn vom Server ein Statuscode für einen nicht schwerwiegenden Fehler zurückgegeben wird, werden die Hedgingaufrufe fortgesetzt. Andernfalls werden ausstehende Anforderungen abgebrochen, und der Fehler wird an die App zurückgegeben. Weitere Informationen zu Statuscodes finden Sie unter Statuscodes und deren Verwendung in gRPC. |