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.
Muster des Leistungsschalters
Absicht
Das Circuit Breaker-Muster kann verhindern, dass ein Anruferdienst erneut versucht, einen anderen Dienst (Anrufer) anzurufen, obwohl der Anruf zuvor zu wiederholten Timeouts oder Ausfällen geführt hat. Das Muster wird auch verwendet, um zu erkennen, wann der angerufene Dienst wieder funktionsfähig ist.
Motivation
Wenn mehrere Microservices zusammenarbeiten, um Anfragen zu bearbeiten, kann es sein, dass ein oder mehrere Dienste nicht verfügbar sind oder eine hohe Latenz aufweisen. Wenn komplexe Anwendungen Microservices verwenden, kann ein Ausfall eines Microservices zum Ausfall der Anwendung führen. Microservices kommunizieren über Remote-Prozeduraufrufe, und es können vorübergehende Fehler bei der Netzwerkkonnektivität auftreten, die zu Ausfällen führen. (Die vorübergehenden Fehler können mithilfe des Musters „Wiederholungsversuch mit Backoff“ behandelt werden.) Während der synchronen Ausführung kann die Kaskadierung von Timeouts oder Ausfällen zu einer schlechten Benutzererfahrung führen.
In einigen Situationen kann es jedoch länger dauern, bis die Fehler behoben sind, z. B. wenn der aufgerufene Dienst ausgefallen ist oder ein Datenbankkonflikt zu Timeouts führt. In solchen Fällen, wenn der aufrufende Dienst die Aufrufe wiederholt wiederholt, können diese Wiederholungen zu Netzwerkkonflikten und zur Auslastung des Datenbank-Threadpools führen. Wenn mehrere Benutzer die Anwendung wiederholt wiederholen, verschlimmert sich das Problem zusätzlich und kann zu Leistungseinbußen in der gesamten Anwendung führen.
Das Circuit Breaker Pattern wurde von Michael Nygard in seinem Buch Release It (Nygard 2018) populär gemacht. Dieses Entwurfsmuster kann verhindern, dass ein Anruferdienst einen Serviceanruf wiederholt, der zuvor zu wiederholten Timeouts oder Ausfällen geführt hat. Es kann auch erkennen, wann der angerufene Dienst wieder funktionsfähig ist.
Schutzschalterobjekte funktionieren wie elektrische Schutzschalter, die den Strom automatisch unterbrechen, wenn im Stromkreis eine Störung auftritt. Elektrische Schutzschalter schalten den Stromfluss ab oder lösen ihn aus, wenn eine Störung vorliegt. In ähnlicher Weise befindet sich das Schutzschalter-Objekt zwischen dem Anrufer und dem angerufenen Dienst und löst aus, wenn der Anrufer nicht verfügbar ist.
Die Irrtümer des verteilten Rechnens
Während eines Netzwerkausfalls warten Anwendungen möglicherweise auf unbestimmte Zeit auf eine Antwort und verbrauchen kontinuierlich Anwendungsressourcen. Wenn die Vorgänge nicht wiederholt werden, wenn das Netzwerk wieder verfügbar ist, kann dies ebenfalls zu einer Verschlechterung der Anwendung führen. Wenn bei API Aufrufen einer Datenbank oder eines externen Dienstes aufgrund von Netzwerkproblemen ein Timeout auftritt, können wiederholte Anrufe ohne Schutzschalter Kosten und Leistung beeinträchtigen.
Anwendbarkeit
Verwenden Sie dieses Muster, wenn:
-
Der Anruferdienst tätigt einen Anruf, der höchstwahrscheinlich fehlschlagen wird.
-
Eine hohe Latenz, die der angerufene Dienst aufweist (z. B. wenn die Datenbankverbindungen langsam sind), führt zu Timeouts beim angerufenen Dienst.
-
Der Anruferdienst tätigt einen synchronen Anruf, aber der angerufene Dienst ist nicht verfügbar oder weist eine hohe Latenz auf.
Fehler und Überlegungen
-
Dienstunabhängige Implementierung: Um zu verhindern, dass der Code aufgebläht wird, empfehlen wir, das Circuit-Breaker-Objekt auf Microservice-unabhängige und -gesteuerte Weise zu implementieren. API
-
Schließung des Stromkreises durch den Angerufenen: Wenn der Angerufene das Leistungsproblem oder den Ausfall behoben hat, kann er den Verbindungsstatus auf ändern.
CLOSED
Dies ist eine Erweiterung des Schutzschaltermusters und kann implementiert werden, wenn Ihr Wiederherstellungszeitziel (RTO) dies erfordert. -
Multithread-Anrufe: Der Wert für das Ablauf-Timeout ist definiert als der Zeitraum, für den die Verbindung ausgelöst bleibt, bevor Anrufe erneut weitergeleitet werden, um die Verfügbarkeit des Dienstes zu überprüfen. Wenn der angerufene Dienst in mehreren Threads aufgerufen wird, definiert der erste fehlgeschlagene Anruf den Wert für das Ablauftimeout. Ihre Implementierung sollte sicherstellen, dass bei nachfolgenden Aufrufen das Ablauftimeout nicht endlos verschoben wird.
-
Erzwungenes Öffnen oder Schließen des Stromkreises: Systemadministratoren sollten in der Lage sein, einen Kreislauf zu öffnen oder zu schließen. Dies kann erreicht werden, indem der Wert für das Ablauftimeout in der Datenbanktabelle aktualisiert wird.
-
Beobachtbarkeit: In der Anwendung sollte eine Protokollierung eingerichtet sein, um die Anrufe zu identifizieren, die fehlschlagen, wenn der Schutzschalter geöffnet ist.
Implementierung
Hochrangige Architektur
Im folgenden Beispiel ist der Anrufer der Bestelldienst und der Angerufene der Zahlungsdienst.
Liegen keine Ausfälle vor, leitet der Bestellservice alle Anrufe über den Schutzschalter an den Zahlungsdienst weiter, wie das folgende Diagramm zeigt.
Wenn beim Zahlungsdienst ein Timeout auftritt, kann der Schutzschalter den Timeout erkennen und den Ausfall nachverfolgen.
Wenn die Timeouts einen bestimmten Schwellenwert überschreiten, öffnet die Anwendung den Stromkreis. Wenn der Stromkreis geöffnet ist, leitet das Circuit Breaker-Objekt die Anrufe nicht an den Zahlungsdienst weiter. Wenn der Bestellservice den Zahlungsdienst aufruft, wird sofort ein Fehler gemeldet.
Das Circuit Breaker-Objekt versucht in regelmäßigen Abständen festzustellen, ob die Aufrufe an den Zahlungsdienst erfolgreich waren.
Wenn der Anruf beim Zahlungsdienst erfolgreich ist, wird die Verbindung geschlossen und alle weiteren Anrufe werden wieder an den Zahlungsdienst weitergeleitet.
Implementierung mithilfe von AWS Diensten
Die Beispiellösung verwendet Express-Workflows AWS Step Functions
Die Lösung verwendet auch eine Amazon DynamoDB-Tabelle
Wenn ein Dienst einen anderen Dienst aufrufen möchte, startet er den Workflow mit dem Namen des aufgerufenen Dienstes. Der Workflow ruft den Circuit Breaker-Status aus der CircuitStatus
DynamoDB-Tabelle ab, in der die aktuell heruntergestuften Dienste gespeichert sind. CircuitStatus
Enthält er einen noch nicht abgelaufenen Datensatz für den Angerufenen, ist der Circuit geöffnet. Der Step Functions Functions-Workflow gibt einen sofortigen Fehler zurück und wird mit einem FAIL
Status beendet.
Wenn die CircuitStatus
Tabelle keinen Datensatz für den Angerufenen oder einen abgelaufenen Datensatz enthält, ist der Dienst betriebsbereit. Der ExecuteLambda
Schritt in der State-Machine-Definition ruft die Lambda-Funktion auf, die über einen Parameterwert gesendet wird. Wenn der Aufruf erfolgreich ist, wird der Step Functions Functions-Workflow mit einem SUCCESS
Status beendet.
Schlägt der Serviceaufruf fehl oder tritt ein Timeout auf, versucht die Anwendung es mit exponentiellem Backoff für eine bestimmte Anzahl von Malen erneut. Schlägt der Serviceaufruf nach den Wiederholungen fehl, fügt der Workflow einen Datensatz mit dem Zeichen an in die CircuitStatus
Tabelle für den Dienst einExpiryTimeStamp
, und der Workflow wird mit einem Status beendet. FAIL
Bei nachfolgenden Aufrufen desselben Dienstes wird sofort ein Fehler gemeldet, sofern der Schutzschalter geöffnet ist. Der Get Circuit Status
Schritt in der State-Machine-Definition überprüft die Verfügbarkeit des Dienstes anhand des ExpiryTimeStamp
Werts. Abgelaufene Elemente werden mithilfe der DynamoDB-Funktion time to live (TTL) 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-Sprachanweisungen im Step Functions 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