Leistungsschaltermuster - AWS Präskriptive Leitlinien

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Leistungsschaltermuster

Absicht

Das Leistungsschaltermuster kann verhindern, dass ein Aufruferservice einen Aufruf an einen anderen Service (Anrufempfänger) wiederholt, wenn der Aufruf zuvor wiederholte Timeouts oder Fehler verursacht hat. Das Muster wird auch verwendet, um zu erkennen, wann der Anruferservice wieder funktioniert.

Motivation

Wenn mehrere Microservices zusammenarbeiten, um Anfragen zu bearbeiten, können ein oder mehrere Services nicht verfügbar sein oder eine hohe Latenz aufweisen. Wenn komplexe Anwendungen Microservices verwenden, kann ein Ausfall in einem Microservice zu Anwendungsausfällen führen. Microservices kommunizieren über Remote-Prozeduraufrufe, und es können vorübergehende Fehler in der Netzwerkkonnektivität auftreten, die zu Fehlern führen. (Die vorübergehenden Fehler können mithilfe des Wiederholungsversuchs mit Backoff-Muster behandelt werden.) Während der synchronen Ausführung kann die Kaskadierung von Timeouts oder Fehlern zu einer schlechten Benutzererfahrung führen.

In einigen Situationen können die Fehler jedoch länger dauern, z. B. wenn der Aufruferservice ausgefallen ist oder ein Datenbankkonflikt zu Timeouts führt. Wenn der aufrufende Service die Aufrufe wiederholt wiederholt wiederholt, können diese Wiederholungen zu Netzwerkkonflikten und der Nutzung des Datenbank-Threadpools führen. Wenn mehrere Benutzer die Anwendung wiederholt wiederholen, verschlimmert dies das Problem und kann zu Leistungseinbußen in der gesamten Anwendung führen.

Das Leistungsschaltermuster wurde von Bol Nygard in seinem Buch Release It (Nygard 2018) verbreitet. Dieses Designmuster kann verhindern, dass ein Anruferservice einen Serviceaufruf wiederholt, der zuvor wiederholte Timeouts oder Fehler verursacht hat. Es kann auch erkennen, wann der Anruferservice wieder funktioniert.

Schutzschalterobjekte funktionieren wie Schutzschalter, die den Strom automatisch unterbrechen, wenn eine Anomalie in der Verbindung vorliegt. Schutzschalter schalten den Fluss des Stroms ab oder schalten ihn aus, wenn ein Fehler auftritt. In ähnlicher Weise befindet sich das Schutzschalterobjekt zwischen dem Aufrufer und dem Aufruferdienst und wird ausgelöst, wenn der Aufrufer nicht verfügbar ist.

Die Fallzeiten verteilter Datenverarbeitung sind eine Reihe von Aussagen, die von Deutsch und anderen bei Sun Microsystems erstellt wurden. Sie sagen, dass Programmierer, die neu bei verteilten Anwendungen sind, immer falsche Annahmen treffen. Die Netzwerkzuverlässigkeit, die Erwartungen an Nulllatenz und Bandbreitenbeschränkungen führen dazu, dass Softwareanwendungen mit minimaler Fehlerbehandlung für Netzwerkfehler geschrieben werden.

Während eines Netzwerkausfalls warten Anwendungen möglicherweise auf unbestimmte Zeit auf eine Antwort und verbrauchen kontinuierlich Anwendungsressourcen. Wenn die Operationen nicht wiederholt werden, wenn das Netzwerk verfügbar ist, kann dies auch zu einer Beeinträchtigung der Anwendung führen. Wenn API-Aufrufe an eine Datenbank oder einen externen Service aufgrund von Netzwerkproblemen ausfallen, können sich wiederholte Aufrufe ohne Leistungsschalter auf Kosten und Leistung auswirken.

Anwendbarkeit

Verwenden Sie dieses Muster, wenn:

  • Der Anruferservice führt einen Aufruf durch, der höchstwahrscheinlich fehlschlägt.

  • Eine hohe Latenz, die der Aufruferservice zeigt (z. B. wenn Datenbankverbindungen langsam sind), führt zu Timeouts für den Aufruferservice.

  • Der Anruferservice führt einen synchronen Aufruf durch, aber der Anruferservice ist nicht verfügbar oder weist eine hohe Latenz auf.

Fehler und Überlegungen

  • Serviceunabhängige Implementierung: Um eine Überlastung des Codes zu verhindern, empfehlen wir Ihnen, das Schutzschalterobjekt auf Microservice-unabhängige und API-gesteuerte Weise zu implementieren.

  • Schließen des Kreises durch den Aufrufer: Wenn der Aufrufer nach dem Leistungsproblem oder -fehler wiederhergestellt ist, kann er den Verbindungsstatus auf aktualisierenCLOSED. Dies ist eine Erweiterung des Leistungsschaltermusters und kann implementiert werden, wenn Ihr Recovery Time Objective (RTO) dies erfordert.

  • Multithread-Aufrufe: Der Ablauf-Timeout-Wert ist definiert als der Zeitraum, in dem die Verbindung ausgelöst wird, bevor Aufrufe erneut weitergeleitet werden, um die Serviceverfügbarkeit zu überprüfen. Wenn der Aufrufer-Service in mehreren Threads aufgerufen wird, definiert der erste fehlgeschlagene Aufruf den Ablauf-Timeout-Wert. Ihre Implementierung sollte sicherstellen, dass nachfolgende Aufrufe das Ablauf-Timeout nicht unbegrenzt verschieben.

  • Öffnen oder Schließen der Verbindung erzwingen: Systemadministratoren sollten eine Verbindung öffnen oder schließen können. Dazu aktualisieren Sie den Ablauf-Timeout-Wert in der Datenbanktabelle.

  • Beobachtbarkeit: Für die Anwendung sollte die Protokollierung eingerichtet sein, um die Aufrufe zu identifizieren, die fehlschlagen, wenn der Schutzschalter geöffnet ist.

Implementierung

Hochrangige Architektur

Im folgenden Beispiel ist der Aufrufer der Bestellservice und der Aufrufer der Zahlungsservice.

Wenn es keine Fehler gibt, leitet der Bestellservice alle Aufrufe über den Leistungsschalter an den Zahlungsservice weiter, wie das folgende Diagramm zeigt.

Schutzschaltermuster ohne Fehler.

Wenn der Zahlungsservice eine Zeitüberschreitung aufweist, kann der Leistungsschalter die Zeitüberschreitung erkennen und den Fehler verfolgen.

Schutzschalter mit Zahlungsdienstausfall.

Wenn die Timeouts einen bestimmten Schwellenwert überschreiten, öffnet die Anwendung die -schaltung. Wenn die Verbindung geöffnet ist, leitet das Leistungsschalterobjekt die Aufrufe nicht an den Zahlungsservice weiter. Sie gibt einen sofortigen Fehler zurück, wenn der Bestellservice den Zahlungsservice aufruft.

Der Schutzschalter stoppt das Routing an den Zahlungsservice.

Das Leistungsschalterobjekt versucht regelmäßig zu sehen, ob die Aufrufe des Zahlungsservices erfolgreich sind.

Der Schutzschalter wiederholt den Zahlungsservice regelmäßig.

Wenn der Aufruf an den Zahlungsservice erfolgreich ist, wird die Verbindung geschlossen und alle weiteren Aufrufe werden erneut an den Zahlungsservice weitergeleitet.

Schutzschalter mit funktionierendem Zahlungsservice.

Implementierung mithilfe von AWS-Services

Die Beispiellösung verwendet Express-Workflows in AWS Step Functions , um das Leistungsschaltermuster zu implementieren. Mit dem Step-Functions-Zustandsautomaten können Sie die Wiederholungsfunktionen und den entscheidungsbasierten Kontrollablauf konfigurieren, die für die Musterimplementierung erforderlich sind.

Die Lösung verwendet auch eine Amazon-DynamoDB-Tabelle als Datenspeicher, um den Verbindungsstatus zu verfolgen. Dies kann zur Verbesserung der Leistung durch einen In-Memory-Datenspeicher wie Amazon ElastiCache für Redis ersetzt werden.

Wenn ein Service einen anderen Service aufrufen möchte, startet er den Workflow mit dem Namen des Aufruferservices. Der Workflow ruft den Leistungsschalterstatus aus der DynamoDB-CircuitStatusTabelle ab, in der die aktuell beeinträchtigten Services gespeichert sind. Wenn einen nicht abgelaufenen Datensatz für den Aufrufer CircuitStatus enthält, ist die Verbindung geöffnet. Der Step Functions-Workflow gibt einen sofortigen Fehler zurück und wird mit dem FAIL Status beendet.

Wenn die CircuitStatus Tabelle keinen Datensatz für den Aufrufer oder einen abgelaufenen Datensatz enthält, ist der Service betriebsbereit. Der ExecuteLambda Schritt in der Definition des Zustandsautomaten ruft die Lambda-Funktion auf, die über einen Parameterwert gesendet wird. Wenn der Aufruf erfolgreich ist, wird der Step-Functions-Workflow mit dem SUCCESS Status beendet.

Implementierung des Schutzschalters mit AWS Step Functions und DynamoDB .

Wenn der Serviceaufruf fehlschlägt oder ein Timeout auftritt, wiederholt die Anwendung den Vorgang mit exponentiellem Backoff für eine bestimmte Anzahl von Malen. Wenn der Serviceaufruf nach dem erneuten Versuch fehlschlägt, fügt der Workflow einen Datensatz in die CircuitStatus Tabelle für den Service mit einem ein ExpiryTimeStampund der Workflow wird mit einem -FAILStatus beendet. Nachfolgende Aufrufe desselben Services geben einen sofortigen Fehler zurück, solange der Leistungsschalter geöffnet ist. Der Get Circuit Status Schritt in der Definition des Zustandsautomaten überprüft die Serviceverfügbarkeit basierend auf dem ExpiryTimeStamp Wert . Abgelaufene Elemente werden mithilfe der DynamoDB-TTL-Funktion (Time to Live) aus der CircuitStatus Tabelle gelöscht.

Beispiel-Code

Der folgende Code verwendet die GetCircuitStatus Lambda-Funktion, um den Status des Leistungsschalters zu überprüfen.

var serviceDetails = _dbContext.QueryAsync<CircuitBreaker>(serviceName, QueryOperator.GreaterThan, new List<object> {currentTimeStamp}).GetRemainingAsync(); if (serviceDetails.Result.Count > 0) { functionData.CircuitStatus = serviceDetails.Result[0].CircuitStatus; } else { functionData.CircuitStatus = ""; }

Der folgende Code zeigt die Amazon States Language-Anweisungen im Step Functions-Workflow.

"Is Circuit Closed": { "Type": "Choice", "Choices": [ { "Variable": "$.CircuitStatus", "StringEquals": "OPEN", "Next": "Circuit Open" }, { "Variable": "$.CircuitStatus", "StringEquals": "", "Next": "Execute Lambda" } ] }, "Circuit Open": { "Type": "Fail" }

GitHub -Repository

Eine vollständige Implementierung der Beispielarchitektur für dieses Muster finden Sie im GitHub Repository unter https://github.com/aws-samples/circuit-breaker-netcore-blog.

Blog-Referenzen

Verwandter Inhalt