Start / Seminare / Quarkus für Spring-Boot-Teams
Modul
Resiliente und reaktive Anwendungen
4 Kapitel in diesem Modul-Video · Laufzeit
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
Resiliente und reaktive Anwendungen
0:00 Willkommen zum dritten Tag. Ab jetzt geht es nicht mehr um Übertragung, sondern um Betrieb. Und wir beginnen mit einem Thema, bei dem oft zwei Dinge vermischt werden: Reaktivität und Resilienz. Reaktiv ist ein Programmiermodell für bestimmte Lastprofile. Resilienz ist die Fähigkeit, mit Störungen umzugehen. Das erste brauchen die wenigsten Dienste, das zweite brauchen alle.
0:23 In diesem Modul bekommen Sie beides — und eine klare Empfehlung, womit Sie anfangen sollten.
Resiliente und reaktive Anwendungen
0:30 Der dritte Tag hat einen anderen Charakter als die ersten beiden. Es geht um Betrieb und Entscheidung: Resilienz, Observability, Container und Kubernetes, Native Image — und am Ende um die Migration selbst und die Roadmap danach. Alles, was Sie heute lernen, dient dazu, die Frage aus Modul eins mit Zahlen zu beantworten statt mit Meinungen.
Imperativ und reaktiv im selben Projekt
0:50 Beginnen wir mit dem Programmiermodell. Quarkus kann beides, und das Wichtigste vorweg: Sie müssen sich nicht für die ganze Anwendung entscheiden. Mutiny ist die reaktive Bibliothek von Quarkus. Zwei Typen genügen zum Einstieg: einer für genau ein Ereignis, einer für einen Strom von Ereignissen. Der Strom setzt Reactive Streams um, einschließlich Gegendruck — der Empfänger sagt also, wie viel er verkraftet. Bei einem einzelnen Ereignis braucht es das nicht.
1:18 Das Bild: ein Einschreiben gegenüber einem Zeitungsabonnement. Beim Einschreiben kommt genau eine Sendung, beim Abo müssen Sie sagen können: bitte langsamer, mein Briefkasten ist voll. Oben der vertraute Weg: aufrufen, warten, Ergebnis. Unten dieselbe Fachlichkeit als Kette von Reaktionen — bei einem Ergebnis dies, bei einem Fehler das.
1:40 Die Lesart ist immer gleich: bei Ereignis X tue Y. Was Sie hier auch sehen, ist der Preis: Die untere Variante ist länger und ihr Kontrollfluss ist nicht mehr der des Programmtexts. Dafür blockiert sie keinen Thread. Ob sich dieser Handel lohnt, hängt einzig an Ihrem Lastprofil — dazu kommen wir im dritten Kapitel. Der entscheidende Punkt ist die Trennung der Threadarten.
2:04 Reaktive Endpunkte laufen auf wenigen Event-Loop-Threads, die niemals blockieren dürfen — blockiert einer, stehen alle Anfragen, die er bedient. Deshalb schlägt der Versuch, in einer Kette auf ein Ergebnis zu warten, auf einem solchen Thread bewusst fehl. Das ist keine Schikane, sondern eine eingebaute Sicherung. Blockierende Arbeit gehört markiert, damit sie auf einen Worker-Thread wandert.
2:27 Und der letzte Punkt wird gern unterschätzt: Kontextinformationen wie Sicherheitsidentität oder Traces müssen über die Kette hinweg mitgeführt werden. Der erste Punkt ist der häufigste und der folgenreichste: ein blockierender Datenbankaufruf in einer reaktiven Kette. Unter geringer Last fällt das nie auf, unter hoher Last bricht alles gleichzeitig ein.
2:48 Der zweite ist ein Anfängerfehler mit hohem Verwirrungspotenzial: Die Kette wird gebaut, aber nie abonniert — es passiert schlicht nichts, ohne Fehlermeldung. Der dritte betrifft die Fehlersuche: Stacktraces zeigen die Kette statt der Ursache. Und der vierte ist eine Teamfrage: Ein einzelner reaktiver Endpunkt zwingt alle, das Modell zu verstehen.
Fehlertoleranz
3:09 Und jetzt zu dem Teil, der fast allen Diensten mehr bringt als jede Reaktivität: der Umgang mit Störungen bei Aufrufen fremder Systeme. Die Extension setzt MicroProfile Fault Tolerance um und bringt fünf Werkzeuge mit: Wiederholung, Zeitgrenze, Deckelung der Nebenläufigkeit, Abtrennung eines kranken Aufrufs und eine Ersatzantwort.
3:29 Das Bild: eine Sicherung im Stromkasten. Sie verhindert nicht, dass ein Gerät kaputtgeht — sie verhindert, dass das kaputte Gerät das ganze Haus dunkel macht. Genau das ist die Aufgabe eines Circuit Breakers: Er schützt nicht den fremden Dienst, er schützt Sie vor ihm. Und noch eine Einordnung: Von diesen fünf Werkzeugen brauchen die meisten Dienste zwei — eine Zeitgrenze und eine Ersatzantwort.
3:53 Alles Weitere ist sinnvoll, aber selten der erste Schritt. Diese Zahlen lohnt es sich zu kennen, weil sie gelten, wenn Sie nichts sagen. Besonders die Zeitgrenze von einer Sekunde überrascht regelmäßig — das ist streng, und in vielen Umgebungen zu streng. Beim Circuit Breaker geht es um die Kombination: Erst wird eine Mindestzahl von Aufrufen beobachtet, dann entscheidet der Fehleranteil, dann wird eine Zeit lang gar nicht mehr durchgelassen.
4:18 Wenn Ihr Beobachtungsfenster größer ist als der übliche Verkehr in dieser Zeit, öffnet der Circuit Breaker nie. Und die Fußnote zeigt, dass sich all das je Methode aus der Konfiguration steuern lässt. Vier Annotationen über einer Methode, und darunter die Ersatzmethode mit derselben Signatur — das ist Pflicht, sonst findet das Framework sie nicht.
4:38 Wichtig ist, was hier mathematisch passiert: Zwei Wiederholungen bei zwei Sekunden Zeitgrenze bedeuten im schlechtesten Fall sechs Sekunden, bevor der Aufrufer etwas hört. Rechnen Sie das immer durch und vergleichen Sie es mit der Geduld Ihres Aufrufers. Und die Fußnote ist ein netter Nebeneffekt: Die Extension erzeugt von sich aus Metriken — Sie können also messen, ob Ihre Einstellungen greifen.
5:01 Der erste Punkt ist genau die Rechnung von eben: Wiederholung ohne Zeitgrenze verlängert den Ausfall, statt ihn abzufangen. Der zweite betrifft die Art des Fehlers — ein dauerhafter Fehler wird durch Wiederholung nicht besser, er kostet nur Zeit und Last. Der dritte ist ein Vertrauensproblem: Der Fallback liefert veraltete Daten, ohne das kenntlich zu machen; markieren Sie solche Antworten, sonst trifft jemand Entscheidungen auf einer stillen Ersatzantwort.
5:27 Und der vierte ist die Fensterfrage vom Tabellenblatt: Der Circuit Breaker öffnet nie.
Wann reaktiv sinnvoll ist
5:32 Zurück zur Ausgangsfrage. Reaktiv ist kein Reifegrad und kein Qualitätsmerkmal — es ist ein Werkzeug mit einem klar umrissenen Einsatzbereich. Reaktive Programmierung zahlt sich dort aus, wo viele gleichzeitige Verbindungen überwiegend auf Ein- und Ausgabe warten. Der Gewinn entsteht dadurch, dass wartende Anfragen keinen Thread besetzen.
5:53 Wo dagegen gerechnet wird oder wo eine blockierende Datenbank bedient wird, gibt es nichts zu gewinnen — die Arbeit muss ja trotzdem jemand tun. Das Bild: Ein Kellner kann zwanzig Tische bedienen, solange die Gäste lesen und überlegen. Er kann nicht zwanzig Gerichte gleichzeitig kochen. Die vier Felder beantworten die Frage entlang zweier Achsen. Oben links, viele Verbindungen und wenig Rechenlast, ist der klassische Fall — dort gehört reaktiv hin.
6:20 Unten links genügt das imperative Modell vollkommen, und jede Komplexität wäre verschenkt. Bei viel Rechenlast hilft Reaktivität gar nicht; dort skalieren Sie horizontal oder optimieren den Algorithmus. Suchen Sie Ihre Anwendung ehrlich in diesem Raster — und zwar je Endpunkt, nicht pauschal. Die meisten Anwendungen haben einen oder zwei Endpunkte oben links und viele unten.
6:44 Vier Punkte zur Entscheidung. Das Lastprofil zählt, nicht der Eindruck von Modernität. Jede reaktive Kette erhöht dauerhaft den Aufwand für Fehlersuche und Einarbeitung — das ist eine Kostenposition, die niemand in die Rechnung schreibt. Ein gemischtes Modell ist völlig in Ordnung, aber die Grenze muss benannt und dokumentiert sein.
7:02 Und der letzte Punkt ist die praktische Empfehlung dieses Moduls: Fehlertoleranz wirkt in beiden Modellen und hat in fast allen Projekten die größere Wirkung als eine Umstellung auf reaktiv. Der erste Punkt ist die häufigste Sinnlosigkeit: reaktive Endpunkte vor einer blockierenden Datenbank — der Engpass bleibt genau, wo er war.
7:22 Der zweite ist die Pauschalentscheidung für die ganze Anwendung. Der dritte ist das übliche Problem: Es fehlen Messwerte, und der behauptete Gewinn bleibt unbelegt. Und der vierte ist eine Verwechslung, die man erstaunlich oft hört: Reaktiv wird als Antwort auf Antwortzeitprobleme verkauft, die in Wahrheit fehlende Timeouts sind.
7:41 Timeouts sind billiger und wirken sofort.
Übung
7:44 In der Übung sichern wir den Aufruf des Abrechnungsdienstes ab — und zwar so, dass Sie jede einzelne Einstellung wirken sehen. Das Erfolgskriterium ist bewusst dreiteilig: Antwort innerhalb der Zeitgrenze, ein nachweislich öffnender Circuit Breaker und ein erkennbar gekennzeichneter Fallback. Der dritte Punkt ist der, den man in der Praxis am häufigsten vergisst.
8:06 Wer Zeit übrig hat, setzt genau einen Endpunkt reaktiv um — und schreibt auf, warum der Rest imperativ bleibt. Diese Begründung ist die eigentliche Übung; der Code ist in zehn Minuten geschrieben. Prüfen Sie dabei jede Einstellung einzeln, bevor Sie die nächste hinzunehmen — nur so lässt sich das beobachtete Verhalten überhaupt einer Ursache zuordnen.
8:27 Die Reihenfolge ist der Kern dieser Übung: eine Einstellung nach der anderen, und nach jeder messen. Zuerst die Zeitgrenze bei einem langsamen Dienst. Dann die Wiederholung — und hier bitte die Gesamtdauer messen, das ist der Aha-Moment. Dann der Circuit Breaker, und zwar so eingestellt, dass er in Ihrem Testszenario auch wirklich öffnet. Und zum Schluss der Fallback.
8:48 Die Fußnote nennt das Werkzeug zur Kontrolle: Die Metriken der Extension zeigen Ihnen schwarz auf weiß, ob die Einstellungen greifen. Der erste Punkt ist die Versuchung, alle vier Annotationen sofort zu setzen — dann sehen Sie ein Verhalten, können es aber keiner Einstellung zuordnen. Der zweite ist die Rechnung aus Zeitgrenze mal Wiederholungen, die die Geduld des Aufrufers sprengt.
9:11 Der dritte ist der nicht gekennzeichnete Fallback, der alte Daten wie frische aussehen lässt. Und der vierte ist der rote Faden dieses Seminars: Gemessen wird nur der Erfolgsfall — dabei ist die ganze Fehlertoleranz für den anderen Fall gebaut.
Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →