Michael Nygard über Resilient Software Design

„Die normale Betriebsart heißt: teilweiser Ausfall.“

Redaktion JAXenter, Michael Thomas

Im Interview erläutert Michael Nygard (Cognitect Inc.) seine Sicht auf Resilientes Software-Design. Worauf reagiert der Begriff „Resilienz“? Wo können resiliente Systeme wirklich einen Vorteil bringen? Welche Rolle spielen Microservices, wenn es darum geht, ein System resilient zu machen? Und welche Fehler lauern in der Fehlervermeidung? Zum Schluss gibt Michael noch eine persönliche Einschätzung des „Circuit Breaker Pattern“, das es mittlerweile zu einiger Bekanntheit im Resilient Software Design gebracht hat.

Java Magazin: Warum ist Resilient Software Design derart wichtig, dass wir einen eigenen Begriff dafür benötigen? Warum nennen wir es nicht einfach „ausfallsicher“ oder „fehlersicher“?

Michael Nygard: Wenn wir über Ausfallsicherheit reden, meinen wir tatsächlich, dass ein System auf sichere Art und Weise ausfällt. Resiliente Systeme hingegen erlangen ihren ursprünglichen Betriebszustand zurück. Das ist ein subtiler Unterschied, aber ein wichtiger. Als ich noch im Bereich Operations unterwegs war, stellten wir die Funktionalität wieder her, indem wir alles neu starteten: erst die Anwendung, und wenn das nicht funktionierte, den Host. Meistens mussten wir auch alles, was von der fehlerhaften Komponente abhängig war, neu starten.

Im Gegensatz dazu würde ein resilientes System versagende Komponenten automatisch abtrennen und sie, sobald sie nicht mehr fehlerhaft sind, wieder integrieren.

JM: In der Einleitung Ihres Buchs „Release It“ schreiben Sie: „Wir werden uns auf die Scharen an unlogisch handelnden Nutzern vorbereiten, die absurde und unvorhersehbare Dinge tun.“ Geht es bei Resilienz im Grunde darum – sich dem Chaos der realen Welt, weil man es nicht kontrollieren kann, zu stellen? Und diese Denkweise in Softwarearchitekturen zu übersetzen?

Nygard: In jeder Hinsicht. Wenn wir uns das Nutzerverhalten genauer ansehen, ist der Mangel an Kontrolle offensichtlich. Es mangelt uns ebenfalls an Kontrolle über Teile unserer eigenen Infrastruktur. Betriebssysteme stürzen ab, Anwendungen weisen Bugs auf. Lüfter, CPUs, Laufwerke – alles geht mal kaputt.

Als wir es noch mit kleinen Systemen – zwischen einer Handvoll und einigen Dutzend Maschinen – zu tun hatten, konnten wir den Status „zu 100 Prozent betriebsbereit“ als Normalzustand und jede Abweichung davon als Ausnahmezustand betrachten. Mit der Skalierung der Systeme besagen jedoch alleine schon die Gesetze der Wahrscheinlichkeit, dass der Zustand „zu 100 Prozent betriebsbereit“ sehr selten eintritt. Die normale Betriebsart heißt vielmehr: teilweiser Ausfall.

JM: Für welche Branchen und Industriesparten ist Resilient Software Design besonders wichtig?

Nygard: Für resiliente Systeme – zumindest die Art, über die ich schreibe – sind Ausfälle normal und es ist okay, dass sie im Modus „teilweiser Ausfall“ laufen. Deshalb sind sie für lebenswichtige Anwendungen und Echtzeitanwendungen ungeeignet.

Geeignet hingegen sind sie für Branchen, in denen die Nachfrage unkontrolliert und konstant ist und wo einzelne Transaktionen ohne katastrophale Verluste geopfert werden können. Das trifft auf die meisten Websysteme zu, insbesondere auf den Handel und die herkömmlichen wie sozialen Medien.

JM: Was ist der häufigste, in nicht resilienten Systemen gemachte Fehler?

Nygard: Der mit Abstand häufigste Fehler ist, gar nicht erst über Produktionsoperationen und Ausfälle in der Produktion nachzudenken. Viele Systeme sind eher darauf ausgelegt, die QA-Überprüfung zu bestehen, als den Alltagseinsatz zu überleben.

JM: Wie können Microservices dabei helfen, ein System resilienter zu machen?

Nygard: Ich glaube das ist ein Thema, dem mehr Beachtung geschenkt werden muss, wenn man sich für Microservices entscheidet. Da gilt es, einige subtile Fragen zu klären.

Ich würde sagen, abhängig davon, wie ein System in Services aufgeteilt ist und wie sich jeder Service gestaltet, können Microservices ein System resilienter machen. Für mich ist die Frage nicht, wie groß der Service ist, sondern wie groß die Anfälligkeitsbereiche [failure domains] sind. Eine Microservices-Architektur kann im Grunde ein einziger großer Anfälligkeitsbereich sein, während sich eine andere in ein Dutzend isolierter Anfälligkeitsbereiche aufspalten kann.

Man muss zwei Dimensionen beachten. Zum einen stellt sich die Frage, welche Services für das jeweilige Feature benötigt werden. Ich bezeichne das als Aktivierungsgraphen für Services. Das heißt: Welche Services müssen beteiligt sein, um einen bestimmten Request zu liefern? Je mehr Überschneidungen zwischen den Aktivierungsgraphen der Request-Typen bestehen, desto weniger resilient ist die Architektur. Aus diesem Grund glaube ich, dass die so genannten „Entity Services“ eine schlechte Idee sind; sie neigen dazu, Aktivierungsgraphen mit großen Überschneidungen zu produzieren.

Die zweite zu berücksichtigende Dimension ist, ob einzelne Services über eine einfache Möglichkeit verfügen, Fehler in ihren Abhängigkeiten zu behandeln; es muss auch dann noch auf Requests reagiert werden, wenn bei einigen der Abhängigkeiten eine Zeitüberschreitung vorliegt oder die Verbindung verweigert wird. Das bedeutet, Resilienz sollte in jeden Service eingebaut werden, vorzugsweise mithilfe eines gemeinsamen Frameworks – auf diesem Weg wird die Überwachung und Verwaltung erleichtert.

DevOpsCon Istio Cheat Sheet

Free: BRAND NEW DevOps Istio Cheat Sheet

Ever felt like service mesh chaos is taking over? As a follow-up to our previous cheat sheet featuring the most important commands and functions, DevOpsCon speaker Michael Hofmann has put together the 8 best practices you should keep in mind when using Istio.

JM: Das „Circuit Breaker Pattern“ aus „Release It“ ist mittlerweile eines der wichtigsten Prinzipien des Resilient Software Designs; Hystrix von Netflix ist eine der bekanntesten Implementierungen. Was macht dieses Pattern aus?

Nygard: In einem Gebäude sorgt ein Kurzschluss für einen hohen Stromfluss, der zu einem Brand führt. Um das zu verhindern, setzen Elektriker Sicherungen ein. Diese erkennen Gefahrensituationen und greifen ein, um die Katastrophe abzuwenden. Bezogen auf Software erfüllt diese „elektrische Sicherung“ dieselbe Funktion: Sie sorgt dafür, dass ein teilweiser Ausfall sich nicht zu einem katastrophalen Ausfall auswächst.

In Implementierungsbegriffen gesprochen geht jeder Aufruf an ein externes Interface durch eine Komponente, die nach Fehlern in den Requests an den Provider suchen kann. Wenn zu viele Aufrufe fehlschlagen, heißt das, dass der Provider nicht verfügbar ist. Ob der Provider oder das Netzwerk down ist, ist dabei unerheblich. Für den Caller zählt nur, dass der Service nicht erreichbar ist.

Ohne einen Circuit Breaker müsste jeder Request auf jeden Thread aufs Neue „entdecken“, dass der Provider nicht verfügbar ist, was für gewöhnlich durch eine Zeitüberschreitung erfolgt. Das bedeutet, dass ein Ausfall beim Provider den Verbraucher verlangsamt. Im schlimmsten Fall kommt es zu keiner Zeitüberschreitung, und alle Threads des Callers warten auf Antworten, die niemals eintreffen.

Im Gegensatz dazu würde ein Circuit Breaker die ersten fehlgeschlagenen Aufrufe entdecken und in einen Zustand übergehen, in dem ausgehende Requests schnell abgelehnt werden, ohne dass überhaupt versucht wird, den Provider zu erreichen. Das bedeutet, dass Fehlerreaktionen schnell erfolgen und keine Zeitüberschreitungen auftreten. Die Threads des Callers bleiben so erhalten und stehen für andere Requests zur Verfügung.

Analog zu einer elektrischen Sicherung unterbricht ein Software-Breaker den Service. Er bewahrt auf Kosten der Vollständigkeit die Verfügbarkeit. Das bedeutet, der Caller muss irgendeine sinnvolle Handlung ausführen. Vielleicht kann er eine gecachte Antwort, den Teil einer Seite oder eine andere Art von vermindertem Service übermitteln. Um damit überhaupt irgendeine Art bedeutungsvoller Rückmeldung sicherzustellen, ist ein sehr behutsames Design erforderlich – insbesondere im Falle von Microservices.

Die Fragen stellte Diana Kupfer. Übersetzung: Michael Thomas, Diana Kupfer.

Michael Nygard möchte Entwicklern das Leben leichter machen und gleichzeitig die Messlatte in der Softwareentwicklung höher legen. Seine Leidenschaft und seinen Drang nach Verbesserung teilt er mit allen, die seinen Weg kreuzen (manchmal sogar mit deren Zustimmung). Durch den Umgang mit Systemen, die sich in der Produktion befinden, hat er IT-Betrieb und produktionsreife Software zu schätzen gelernt. Seine Stärken liegen im Bereich hochverfügbarer und skalierbarer Geschäftssysteme. Michael hat mehrere Bücher veröffentlicht, darunter „97 Things Every Software Architect Should Know“ und der Bestseller „Release It“, ein Buch über die Entwicklung von Software, die realen Herausforderungen standhält. Michael arbeitet für Cognitect Inc., das Unternehmen hinter Clojure, ClojureScript, Pedestal und Datomic.

Verwandte Themen:

Geschrieben von
Michael Thomas
Michael Thomas
Michael Thomas studierte Erziehungswissenschaft an der Johannes Gutenberg-Universität Mainz und arbeitet seit 2013 als Freelance-Autor bei JAXenter.de. Kontakt: mthomas[at]sandsmedia.com
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
4000
  Subscribe  
Benachrichtige mich zu: