© Liashko/Shutterstock.com
Resilienz in verteilten Systemen mit Istio oder Hystrix

O Resilience, where art thou?


Je verteilter ein Softwaresystem konzipiert wird, desto mehr sollte über Resilienz nachgedacht werden. Durch die Verteilung kann es immer wieder zu Fehlersituationen beim Aufruf der beteiligten Kommunikationspartner kommen. Um die Auswirkungen dieser Fehler möglichst gering zu halten oder eventuell ganz zu vermeiden, ist es mittlerweile üblich, mit den notwendigen Resilienzpatterns zu arbeiten. Ob man sich besser via Service-Mesh-Werkzeug oder Framework um die Resilienz kümmert? Beide Ansätze haben etwas für sich.

Die meisten Probleme bei der verteilten Kommunikation kommen aus der Infrastruktur, wie zum Beispiel Abbrüche in der Netzwerkverbindung oder langsame Antwortzeiten bis hin zu Time-outs beim Aufruf eines anderen Service, um nur ein paar Beispiele zu nennen. Es existieren seit Jahren eine Menge Frameworks für jede gängige Programmiersprache, um diese Aufrufe abzusichern. Seit Kurzem entstehen allerdings auch sogenannte Service-Mesh-Tools, die den Einsatz von gängigen Resilienzpatterns ermöglichen. Stellt sich also die Frage, warum man Resilienz durch Programmierung in den Services erreichen soll, wenn man die Probleme der Infrastruktur auch in der Infrastruktur selbst, nämlich im Service Mesh, beheben kann.

Notwendigkeit der Resilienz in verteilten Systemen

Die Notwendigkeit von resilienter Kommunikation in verteilten Systemen ist sicherlich nicht neu. Die bekannteste Sammlung von Fehleinschätzungen, die Liste der „Fallacies of Distributed Computing“ [1], wurde schon um die Jahrtausendwende veröffentlicht. Doch jahrelang hat man sich in Projekten nicht sehr intensiv damit beschäftigt. Das lag unter anderem sicherlich daran, dass eher monolithische Systeme entstanden sind, bei denen diese Probleme nicht an erster Stelle standen. Der neue Trend, Systeme für die Cloud zu entwickeln, also Cloud-native, rückt diese Infrastrukturprobleme wieder in den Fokus. Auch in Projekten entsteht mehr und mehr das Mindset, sich diesen Problemen von Anfang an zu widmen.

Frameworks helfen

Eine Möglichkeit, Resilienz zu erreichen, ist der Einsatz von Frameworks. Die bekanntesten Vertreter im Java-Bereich sind zum Beispiel Hystrix [2], Resilience4j [3], Failsafe [4] und MicroProfile Fault Tolerance [5]. All diese Frameworks bieten mehr oder weniger Hilfe bei der Umsetzung folgender Resilienzpatterns an:

  • Time-out

  • Retry

  • Fallback

  • Circuit Breaker

  • Bulkhead

Bei Time-out, Retry, Circuit Breaker und Bulkhead muss der Entwickler im Grunde nur seine Aufrufmethode annotieren oder entsprechend absichern, und schon verläuft die Kommunikation fehlertoleranter. Hier ein Beispiel für einen Circuit Breaker, implementiert mit MicroProfile Fault Tolerance:

@CircuitBreaker(requestVolumeThreshold = 10, failureRatio = 0.5, delay = 1000, successThreshold = 2) public MyResult callServiceB() { ... }

In einem rollierenden Fenster von zehn aufeinanderfolgenden Aufrufen (requestVolumeThreshold) wird ab einer Fehlerquote von 50 Prozent (failureRatio) der Circuit Breaker in den Status open versetzt. Nachfolgende Aufrufe werden dabei für mindestens 1 000 Millisekunden (delay) unterbunden, bevor der Circuit Breaker in den Status half-open versetzt wird. Sollten in diesem Zustand zwei aufeinanderfolgende Aufrufe erfolgreich sein, wird der Circuit Breaker wieder in den Anfangszustand close versetzt.

Bei Fallback muss es dagegen möglich sein, einen alternativen Ablauf in der Businesslogik zu implementieren, sollte der eigentliche Aufruf fehlschlagen. Diese Möglichkeit ist nicht immer gegeben und kann auch nicht ohne die Existenz einer fachlichen Alternative umgesetzt werden. Von daher kann Fallback als ein fachlich motiviertes Resilienzpattern verstanden werden. Die vier anderen Patterns besitzen dagegen einen rein technischen Fokus. Wir kommen darauf zurück, doch zuvor wollen wir uns der Thematik der Resilienz in verteilten Systemen noch von einer anderen Seite her nähern.

Resilienz im Service Mesh

Ein Geflecht, das aus vielen verteilten Systemen besteht, die sich darüber hinaus auch noch gegenseitig aufrufen, wird als Service Mesh bezeichnet. Zur Verwaltung und Überwachung solcher Service Meshes existieren seit Kurzem geeignete Werkzeuge, wie zum Beispiel Istio [6] und Linkerd [7]. Diese Tools können mittlerweile auf den gängigsten Cloudplattformen eingesetzt werden. Beiden Werkzeugen ist eine grundlegende Architekturentscheidung gemein, nämlich der Einsatz eines sogenannten Sidecars. Damit wird ein separater Prozess bezeichnet, der neben dem eigentlichen Service auf dem Zielknoten installiert wird. Im Fall von Kubernetes besteht ein Kubernetes Pod somit aus dem Service und einem zugehörigen Sidecar. Eine weitere wichtige Eigenschaft des Sidecars ist es, dass sämtliche Kommunikation von und zum Service durch den Sidecar-Prozess geleitet wird. Diese Umlenkung der Kommunikation ist für den Service völlig transpare...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang