Entwurf mit Blick auf Selbstreparatur

Entwerfen Sie Ihre Anwendung so, dass sie bei Ausfällen eine Selbstreparatur durchführt.

In einem verteilten System sind Fehler zu erwarten. Hardware kann ausfallen. Im Netzwerk können vorübergehende Fehler auftreten. Es wird selten vorkommen, dass ein ganzer Dienst, ein Rechenzentrum oder sogar eine gesamte Azure-Region von einer Unterbrechung betroffen ist. Jedoch müssen Sie auch diese Szenarien in Ihre Workloadarchitektur einbeziehen. Resilienz und Wiederherstellung sollten frühzeitig in Ihrem Workloaddesign berücksichtigt werden.

Entwerfen Sie daher eine Anwendung, die bei Ausfällen eine Selbstreparatur durchführt. Dies erfordert einen dreifachen Ansatz:

  • Erkennen von Ausfällen.
  • Ordnungsgemäßes Reagieren auf Ausfälle.
  • Protokollieren und Überwachen von Ausfällen, um Einblick in die Abläufe zu gewinnen.

Ihre Reaktion auf einen bestimmten Typ von Ausfällen hängt von den Anforderungen an die Verfügbarkeit der Anwendung ab. Wenn Sie beispielsweise Hochverfügbarkeit gewährleisten müssen, können Sie die Bereitstellung in mehreren Verfügbarkeitszonen in einer Region durchführen. Damit es selbst in dem unwahrscheinlichen Fall, dass eine gesamte Azure-Region von einer Störung betroffen ist, nicht zu Unterbrechungen kommt, können Sie während eines regionalen Ausfalls ein automatisches Failover zu einer sekundären Region durchführen. Dies ist jedoch mit höheren Kosten und einer potenziell geringeren Leistung verbunden als die Bereitstellung in einer einzigen Region.

Berücksichtigen Sie zudem nicht nur umfangreiche Ereignisse, z. B. regionale Ausfälle, die in der Regel selten auftreten. Sie sollten sich mindestens in gleichem Ausmaß mit der Behandlung lokaler, kurzfristiger Ausfälle, z. B. dem Ausfall von Netzwerk- oder Datenbankverbindungen, befassen.

Empfehlungen

Verwenden Sie entkoppelte Komponenten, die asynchron kommunizieren. Komponenten sollten im Idealfall anhand von Ereignissen miteinander zu kommunizieren. Dies trägt dazu bei, die Wahrscheinlichkeit kaskadierender Fehlern zu minimieren.

Wiederholen Sie fehlgeschlagene Vorgänge. Vorübergehende Fehler werden möglicherweise durch eine kurze Trennung der Netzwerkverbindung, einen Verlust der Verbindung mit der Datenbank oder eine Zeitüberschreitung bei zu hoher Auslastung eines Diensts verursacht. Integrieren Sie zur Behandlung vorübergehender Fehler Wiederholungslogik in die Anwendung. Für viele Azure-Dienste werden automatische Wiederholungen durch das Client-SDK implementiert. Weitere Informationen finden Sie unter Behandeln vorübergehender Fehler und unter Wiederholungsmuster.

Schützen Sie ausgefallene Remotedienste (Trennschalter) . Es empfiehlt sich, nach einem vorübergehenden Fehler den Vorgang zu wiederholen. Wenn jedoch der Fehler weiterhin auftritt, treffen möglicherweise zu viele Aufrufe auf den ausgefallenen Dienst. Dies kann zu kaskadierenden Fehlern führen, wenn sich Anforderungen aufstauen. Verwenden Sie das Trennschalter-Muster, um Fail-Fast-fähig zu sein (ohne den Remoteaufruf auszuführen), wenn eine hohe Wahrscheinlichkeit besteht, dass ein Vorgang nicht erfolgreich ist.

Isolieren Sie kritische Ressourcen (Bulkhead) . Fehler in einem Subsystem können manchmal kaskadiert werden. Dies kann passieren, wenn aufgrund eines Fehlers einige Ressourcen, z. B. Threads oder Sockets, nicht rechtzeitig freigegeben werden und die Ressourcen erschöpft sind. Um dies zu vermeiden, sollten Sie das Bulkhead-Muster verwenden, um ein System in isolierte Gruppen zu partitionieren, damit ein Ausfall in einer Partition nicht zum Ausfall des gesamten Systems führt.

Führen Sie einen Lastenausgleich aus. Für Anwendungen kann es zu plötzlichen Datenverkehrsspitzen kommen, die von Diensten auf dem Back-End nicht mehr bewältigt werden können. Verwenden Sie zur Vermeidung das warteschlangenbasierte Lastenausgleichsmuster, um Arbeitselemente für die asynchrone Ausführung in die Warteschlange einzureihen. Die Warteschlange fungiert als Puffer, um Lastspitzen zu glätten.

Führen Sie ein Failover aus. Wenn eine Instanz nicht erreicht werden kann, führen Sie ein Failover zu einer anderen Instanz aus. Platzieren Sie für zustandslose Elemente, z. B. einen Webserver, mehrere Instanzen hinter einem Lastenausgleich oder Traffic Manager. Verwenden Sie für Elemente, die Zustände speichern, z. B. eine Datenbank, Replikate und Failover. Je nach Datenspeicher und der Art seiner Replikation muss in der Anwendung möglicherweise letztliche Konsistenz verwendet werden.

Gleichen Sie fehlgeschlagene Transaktionen aus. Vermeiden Sie generell verteilte Transaktionen, da sie die Koordination zwischen Diensten und Ressourcen erfordern. Stellen Sie stattdessen einen Vorgang aus kleineren einzelnen Transaktionen zusammen. Wenn der Vorgang während der Ausführung fehlschlägt, machen Sie die bereits abgeschlossenen Schritte mithilfe ausgleichender Transaktionen rückgängig.

Verwenden Sie für lang andauernde Transaktionen Prüfpunkte. Prüfpunkte können Resilienz ermöglichen, wenn ein lang andauernder Vorgang fehlschlägt. Wenn der Vorgang neu gestartet wird (wenn er z. B. von einer anderen VM ausgewählt wird), kann er ab dem letzten Prüfpunkt fortgesetzt werden. Implementieren Sie ggf. einen Mechanismus, der in regelmäßigen Abständen Zustandsinformationen zur Aufgabe aufzeichnet und diesen Zustand in einem langlebigen Speicher speichert, auf den jede Instanz des Prozesses, der die Aufgabe ausführt, zugreifen kann. Wenn der Prozess heruntergefahren wird, kann die von ihm ausgeführte Arbeit auf diese Weise am letzten Prüfpunkt mithilfe einer anderen Instanz fortgesetzt werden. Manche Bibliotheken, wie z. B. NServiceBus und MassTransit, stellen diese Funktionalität bereit. Sie halten den Zustand transparent aufrecht, wobei die Intervalle auf die Verarbeitung von Nachrichten aus Warteschlangen in Azure Service Bus abgestimmt sind.

Stufen Sie Funktionalität korrekt herab, und erhalten Sie die Reaktionsfähigkeit bei Fehlern. Wenn eine Problemumgehung nicht möglich ist, können Sie manchmal reduzierte Funktionalität bereitstellen, die immer noch hilfreich ist. Stellen Sie sich eine Anwendung vor, in der ein Katalog mit Büchern angezeigt wird. Wenn die Anwendung das Miniaturbild für den Buchdeckel nicht abrufen kann, wird ggf. ein Platzhalterbild angezeigt. Möglicherweise sind gesamte Subsysteme für die Anwendung nicht kritisch. Beispielsweise ist auf einer E-Commerce-Website das Anzeigen von Produktempfehlungen wahrscheinlich weniger kritisch als das Verarbeiten von Bestellungen.

Drosseln Sie Clients. Manchmal erzeugt eine kleine Anzahl von Benutzern eine übermäßige Last, wodurch die Verfügbarkeit der Anwendung für andere Benutzer reduziert wird. Drosseln Sie in einem solchen Fall den Client für einen bestimmten Zeitraum. Weitere Informationen finden Sie unter Drosselungsmuster.

Blockieren Sie schädliche Akteure. Wenn Sie einen Client drosseln, bedeutet dies nicht zwangsläufig, dass der Client böswillig agiert hat. Es bedeutet lediglich, dass der Client das Dienstkontingent überschritten hat. Wenn ein Client jedoch das Kontingent beständig überschreitet oder sich auf sonstige Weise schädlich verhält, können Sie ihn blockieren. Definieren Sie einen Out-of-band-Prozess, damit Benutzer das Aufheben der Blockierung anfordern können.

Wählen Sie eine übergeordnete Instanz aus. Wenn Sie eine Aufgabe koordinieren müssen, wählen Sie einen Koordinator aus, indem Sie eine übergeordnete Instanz auswählen. Auf diese Weise ist der Koordinator kein Single Point of Failure. Wenn der Koordinator ausfällt, wird ein neuer ausgewählt. Statt einen vollkommen neu entwickelten Algorithmus für die Auswahl einer übergeordneten Instanz zu implementieren, sollten Sie eine bereits fertige Lösung verwenden, z. B. Zoekeeper.

Testen Sie mit Fault Injection. Allzu häufig wird der Erfolgspfad gründlich getestet, jedoch nicht der Fehlerpfad. Ein System kann bereits lange Zeit in der Produktion ausgeführt werden, bevor ein Fehlerpfad getestet wird. Testen Sie die Resilienz des Systems bei Fehlern mithilfe von Fault Injection, indem Sie entweder echte Fehler auslösen oder diese simulieren.

Nutzen Sie Chaos Engineering. Chaos Engineering ist eine Erweiterung des Konzepts von Fault Injection. Dabei werden Fehler oder anormale Bedingungen in Produktionsinstanzen eingefügt.

Verwenden von Verfügbarkeitszonen. Viele Azure-Regionen bieten Verfügbarkeitszonen, bei denen es sich um isolierte Gruppen von Rechenzentren innerhalb der Region handelt. Einige Azure-Dienste können zonenbasiert bereitgestellt werden, wodurch sichergestellt wird, dass sie in einer bestimmten Zone platziert werden. Dies kann dazu beitragen, die Latenz bei der Kommunikation zwischen Komponenten innerhalb einer Workload zu verringern. Alternativ können einige Dienste mit Zonenredundanz bereitgestellt werden, was bedeutet, dass Azure die Ressource zur Gewährleistung von Hochverfügbarkeit automatisch zonenübergreifend repliziert. Überlegen Sie, welcher Ansatz die beste Balance aus Vor- und Nachteilen für Ihre Lösung bietet. Weitere Informationen zum Entwerfen Ihrer Lösung für die Verwendung von Verfügbarkeitszonen und Regionen finden Sie unter Empfehlungen für die Verwendung von Verfügbarkeitszonen und Regionen.

Informationen zu einer strukturieren Vorgehensweise für die Selbstreparatur von Anwendungen finden Sie unter Entwerfen zuverlässiger Anwendungen für Azure.