Kapitel 1. Reaktiv in einer Kurzfassung
Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com
Reaktiv ist ein überladenes Wort. Vielleicht hast du schon einmal mit einer Suchmaschine nach " reaktiv" gesucht, um zu verstehen, was es damit auf sich hat. Wenn nicht, keine Sorge - du hast dir eine Menge Verwirrung erspart. Es gibt viele reaktive Dinge: Reaktive Systeme, reaktive Programmierung, reaktive Erweiterungen, reaktive Nachrichtenübermittlung. Jeden Tag tauchen neue auf. Sind all diese "Reaktiven" gleich reaktiv oder unterscheiden sie sich?
Diese Fragen werden wir in diesem Kapitel beantworten. Wir werden einen Blick auf die reaktive Landschaft werfen, um die verschiedenen Nuancen von reaktiv zu identifizieren und dir zu helfen, sie zu verstehen, was sie bedeuten, welche Konzepte mit ihnen verbunden sind und wie sie miteinander in Beziehung stehen. Denn ja, ohne zu viel verraten zu wollen, alle diese "Reaktoren" sind miteinander verbunden.
Hinweis
Wie im Vorwort erwähnt, verwenden wir das Substantiv Reactive mit einem großen R, um all die verschiedenen Facetten der reaktiven Landschaft zusammenzufassen, wie zum Beispiel reaktive Programmierung, reaktive Systeme, reaktive Streams und so weiter.
Was verstehen wir unter reaktiv?
Fangen wir am Anfang an. Vergiss Software und IT für ein paar Minuten und benutze einen altmodischen Ansatz. Wenn wir im Oxford English Dictionary nach reactive suchen, finden wir folgende Definition:
reaktiv(Adjektiv)
1.1 Als Reaktion auf eine Situation handeln, anstatt sie zu schaffen oder zu kontrollieren. 1.2 Die Tendenz haben, chemisch zu reagieren. 1.3 (Physiologie) Eine Immunreaktion auf ein bestimmtes Antigen zeigen. 1.4 (Von einer Krankheit) Durch eine Reaktion auf etwas verursacht. 1.5 (Physik) Mit Reaktanz zu tun haben.
Von diesen Definitionen sind zwei für unseren Kontext relevant. Die erste Definition, die eine Reaktion auf einen Stimulus beschreibt, bezieht sich auf eine Art Reaktion. Reaktiv zu sein bedeutet, auf Stimuli zu reagieren, egal welche. Die Unterdefinition 1.1 besagt, dass reaktiv zu sein auch bedeutet, sich unerwarteten und unkontrollierten Situationen zu stellen. Du wirst im Laufe dieses Buches sehen, dass Cloud-native Anwendungen und verteilte Systeme im Allgemeinen mit vielen dieser Situationen konfrontiert sind. Diese Definitionen sind zwar interessant, gelten aber nicht für Software.Aber wir können diese Definitionen berücksichtigen, um eine neue Definition speziell für Software zu erstellen:
1.6 (Software) Eine Anwendung, die auf Stimuli reagiert, z. B. auf Benutzerereignisse, -anfragen und -ausfälle.
Doch wie du in diesem Buch sehen wirst, geht die heutige Reaktivität weit darüber hinaus. Reaktiv ist ein Ansatz, um dein System in Form von Ereignissen und Abläufen zu entwerfen, zu implementieren und darüber nachzudenken. Bei Reactive geht es darum, reaktionsschnelle, belastbare und elastische Anwendungen zu entwickeln. Bei Reactive geht es auch um die Ressourcennutzung durch effiziente Verwaltung von Ressourcen und Kommunikation. Mit anderen Worten: Bei Reactive geht es darum, bessere verteilte Systeme zu entwerfen und zu bauen, die robuster und effizienter sind. Wir nennen sie reaktive Systeme.
Reaktive Software ist nicht neu
Aber Moment mal, die Definition (1.6), die wir gerade gegeben haben, ist nicht bahnbrechend. Im Gegenteil, du hast vielleicht ein Déjà-vu-Erlebnis, oder? Liegt es nicht in der Natur von Software, auf Benutzereingaben und Signale des Betriebssystems zu reagieren? Wie verhält sich Software, wenn du eine Taste drückst? Warum gibt es dann so viele Bücher, Vorträge und Debatten über Reactive, wenn es sich doch nur um normale Software handelt?1 Bitte habe etwas Geduld; es gibt noch mehr dazu.
Aber du hast Recht: Reaktiv ist nicht neu, sondern ziemlich alt. Wir können die Grundlage der Ideen hinter reaktiver Software bis kurz nach dem Erscheinen von Computern in den 50er Jahren zurückverfolgen. Der DYSEAC, ein Computer der ersten Generation (1954 in Betrieb), nutzte bereits Hardware-Interrupts als Optimierung, um Wartezeiten in Abfrageschleifen zu vermeiden. Dieser Computer war eines der ersten Systeme, das eine reaktive und ereignisgesteuerte Architektur verwendete!
Auf Ereignisse zu reagieren bedeutet, ereignisgesteuert zu sein.Ereignisgesteuerte Software empfängt und produziert Ereignisse. Die empfangenen Ereignisse bestimmen den Programmablauf.Ein grundlegender Aspekt der Ereignissteuerung ist die Asynchronität: Du weißt nicht, wann du Ereignisse empfangen wirst.2 Das ist genau die Definition 1.1 aus dem vorigen Abschnitt. Du kannst nicht planen, wann du Ereignisse erhältst, hast keine Kontrolle darüber, welche Ereignisse du bekommst, und musst darauf vorbereitet sein, sie zu verarbeiten. Das ist die Essenz des Reagierens: asynchron zu sein.
Die reaktive Landschaft
Aus dieser Idee, asynchron und ereignisgesteuert zu sein, haben sich viele Formen von Reactive entwickelt. Die reaktive Landschaft ist breit und überfüllt. Abbildung 1-1 zeigt einen Ausschnitt aus dieser Landschaft und die Beziehungen zwischen den wichtigsten reaktiven Dingen.
Aber vergiss nicht unser Ziel: bessere verteilte Systeme zu bauen - reaktive Systeme. Die anderen "Reaktiven" sind hier, um uns bei der Umsetzung dieser Systeme zu helfen.
Die Gründe für Reactive und insbesondere für reaktive Systeme kommen aus dem Bereich der verteilten Systeme. Wie du in Kapitel 3 sehen wirst, ist es schwer, verteilte Systeme zu bauen.Im Jahr 2013 schrieben Experten für verteilte Systeme die erste Version von "The Reactive Manifesto" und stellten das Konzept der reaktiven Systeme vor.
Ja, du kannst verteilte Systeme bauen, ohne reaktive Prinzipien anzuwenden. Reaktiv bietet eine Blaupause, um sicherzustellen, dass bei der Architektur und Entwicklung deines Systems keine wichtigen bekannten Probleme übersehen wurden. Andererseits kannst du diese Prinzipien auch auf nicht-verteilte Systeme anwenden.
Ein reaktives System ist in erster Linie reaktionsfähig. Es muss Anfragen auch unter Last oder bei Ausfällen zeitnah bearbeiten. Um diese Reaktionsfähigkeit zu erreichen, schlägt das Manifest vor, asynchrone Nachrichtenübermittlung als primäre Methode für die Kommunikation zwischen den Komponenten des Systems zu verwenden. In Kapitel 4 wirst du sehen, wie diese Kommunikationsmethode Elastizität und Ausfallsicherheit ermöglicht, zwei wesentliche Eigenschaften solider verteilter Systeme. Das Ziel dieses Buches ist es, dir zu zeigen, wie du solche reaktiven Systeme mit Quarkus bauen kannst. Reaktive Systeme zu bauen ist also unser primäres Ziel.
Die Integration von asynchronem Message Passing in den Kern verteilter Systeme bleibt nicht ohne Folgen: Deine Anwendung muss asynchronen Code und nonblocking I/O verwenden, also die Fähigkeit des Betriebssystems, I/O-Interaktionen in eine Warteschlange zu stellen, ohne aktiv auf die Fertigstellung warten zu müssen. (Wir behandeln nonblocking I/Os in Kapitel 4). Letzteres ist wichtig, um die Ressourcenauslastung, z. B. von CPU und Speicher, zu verbessern - ein weiterer wichtiger Aspekt von Reactive. Viele Toolkits und Frameworks wie Quarkus, Eclipse Vert.x, Micronaut, Helidon und Netty nutzen nonblocking I/O genau aus diesem Grund: um mit begrenzten Ressourcen mehr zu erreichen.
Um reaktiv zu sein, reicht es jedoch nicht aus, eine Laufzeitumgebung zu haben, die nicht blockierende E/A nutzt. Du musst auch asynchronen Code schreiben, der die nicht blockierenden E/A-Mechanismen berücksichtigt. Andernfalls würden die Vorteile der Ressourcennutzung verschwinden. Asynchronen Code zu schreiben, ist ein Paradigmenwechsel. Von der traditionellen (imperativen), do x; do y;
, musst du deinen Code nun als on event(e) do x; on event(f) do y;
gestalten.
Mit anderen Worten: Um reaktiv zu sein, ist dein System nicht nur eine ereignisgesteuerte Architektur, sondern auch dein Code wird ereignisgesteuert.Einer der einfachsten Ansätze zur Implementierung eines solchen Codes sind Callbacks: Du registrierst Funktionen, die beim Empfang von Ereignissen aufgerufen werden. Wie Futures, Promises und Coroutines basiert jeder andere Ansatz auf Callbacks und bietet APIs auf höherer Ebene.
Hinweis
Du fragst dich vielleicht, warum Tabellenkalkulationen in der Landschaft sind. Tabellenkalkulationen sind reaktiv. Wenn du eine Formel in eine Zelle schreibst und einen Wert änderst, der (in einer anderen Zelle) von der Formel gelesen wird, wird das Ergebnis dieser Formel aktualisiert. Die Zelle reagiert auf die Aktualisierung eines Wertes (Ereignis), und das Ergebnis (Reaktion) ist das neue Ergebnis. Ja, dein Manager ist vielleicht ein besserer reaktiver Entwickler als du! Aber keine Sorge, dieses Buch wird das ändern.
Die reaktive Programmierung, die in Kapitel 5 behandelt wird, ist ebenfalls ein Ansatz zum Schreiben von asynchronem Code. Sie nutzt Datenströme, um deinen Code zu strukturieren. Du beobachtest die Daten, die in diesen Strömen übertragen werden, und reagierst darauf. Die reaktive Programmierung bietet eine leistungsstarke Abstraktion und APIs, um ereignisgesteuerten Code zu gestalten.
Die Verwendung von Datenströmen bringt jedoch ein Problem mit sich: Wenn ein schneller Produzent direkt mit einem langsamen Konsumenten verbunden ist, kann es passieren, dass der Konsument überflutet wird. Wie du sehen wirst, können wir puffern oder einen Message Broker dazwischen schalten, aber stell dir vor, du würdest einen Konsumenten ohne diese Mittel überfluten. Das würde gegen die von Reactive propagierte Reaktionsfähigkeit und Anti-Fragilität verstoßen. Um uns bei diesem Problem zu helfen, schlägt Reactive Streams ein asynchrones und nicht blockierendes Backpressure-Protokoll vor, bei dem der Consumer dem Producer seine Verfügbarkeit signalisiert. Wie du dir vorstellen kannst, ist dies nicht überall anwendbar, da manche Datenquellen nicht verlangsamt werden können.
Die Popularität von Reactive Streams hat in den letzten Jahren zugenommen. RSocket zum Beispiel ist ein Netzwerkprotokoll, das auf Reactive Streams basiert. R2DBC schlägt einen asynchronen Datenbankzugriff mit Reactive Streams vor. Auch RxJava, Project Reactor und SmallRye Mutiny verwenden Reactive Streams, um mit Gegendruck umzugehen. Vert.x schließlich ermöglicht die Abbildung des Vert.x Backpressure-Modells auf Reactive Streams.3
Damit ist unser kurzer Rundgang durch die reaktive Landschaft beendet. Wie gesagt, es gibt viele Begriffe und viele Tools. Aber verliere nie das übergeordnete Ziel von Reactive aus den Augen: bessere verteilte Systeme zu bauen. Das ist der Hauptfokus dieses Buches.
Warum sind reaktive Architekturen so gut für Cloud Native Applications geeignet?
Die Cloud - öffentlich, privat oder hybrid - hat Reactive ins Rampenlicht gerückt. Die Cloud ist ein verteiltes System. Wenn du deine Anwendung in der Cloud betreibst, ist sie mit einem hohen Maß an Unsicherheit konfrontiert. Die Bereitstellung deiner Anwendung kann langsam oder schnell erfolgen oder sogar fehlschlagen. Kommunikationsunterbrechungen aufgrund von Netzwerkausfällen oder Partitionen sind keine Seltenheit. Du kannst auf Quotenbeschränkungen, Ressourcenknappheit undHardwareausfälle stoßen. Einige Dienste, die du nutzt, können zeitweise nicht verfügbar sein oder an andere Standorte verlagert werden.
Die Cloud bietet zwar hervorragende Möglichkeiten für die Infrastrukturebene, deckt aber nur die Hälfte ab. Die zweite Hälfte ist deine Anwendung. Sie muss so konzipiert sein, dass sie Teil eines verteilten Systems ist. Sie muss die Herausforderungen verstehen, die mit der Einbindung in ein solches System verbunden sind.
Die reaktiven Prinzipien, die wir in diesem Buch behandeln, helfen dabei, die inhärenten Unsicherheiten und Herausforderungen verteilter Systeme und Cloud-Anwendungen anzunehmen. Sie werden nicht versteckt - im Gegenteil, sie werden umarmt.
Da Microservices und Serverless Computing zu den wichtigsten Architekturstilen gehören, werden die reaktiven Prinzipien noch wichtiger. Sie können dazu beitragen, dass du dein System auf einer soliden Grundlage entwickelst.
Reaktiv ist keine Silberkugel
Wie alles hat auch Reactive Vor- und Nachteile. Es ist keine Wunderwaffe. Keine Lösung funktioniert überall.
Erinnerst du dich noch an die Microservices in den späten 2010er Jahren? Sie erfreuten sich schnell großer Beliebtheit, und viele Unternehmen setzten sie in Bereichen ein, für die sie vielleicht nicht gut geeignet waren. Dadurch wurde oft ein Problem gegen ein anderes eingetauscht. Ähnlich wie bei Microservice-Architekturen gibt es auch bei reaktiven Architekturen Bereiche, für die sie gut geeignet sind. Sie eignen sich hervorragend für verteilte und Cloud-Anwendungen, können aber bei monolithischen und rechenintensiven Systemen katastrophale Auswirkungen haben. Wenn dein System auf Remote-Kommunikation, Ereignisverarbeitung oder hohe Effizienz angewiesen ist, wird Reactive interessant sein. Wenn dein System hauptsächlich prozessinterne Interaktionen nutzt, nur wenige Anfragen pro Tag bearbeitet oder rechenintensiv ist, wird Reactive nichts als Komplexität bringen.
Mit Reactive stellst du das Konzept der Ereignisse in den Mittelpunkt deines Systems. Wenn du an die traditionelle synchrone und imperative Art der Anwendungsentwicklung gewöhnt bist, kann der Weg zu Reactive steil sein. Die Notwendigkeit, asynchron zu werden, bringt die meisten traditionellen Frameworks durcheinander. Wir entfernen uns von den bekannten Remote Procedure Call (RPC) und HTTP-Endpunkten. Nach dieser Vorbemerkung ist es an der Zeit, unsere Reise zu beginnen!
1 Auf YouTube findest du eine Fülle von Vorträgen über Reactive.
2 Asynchron ist das Gegenteil von synchron. Asynchron zu sein bedeutet, dass es zu einem anderen Zeitpunkt passiert, während synchron bedeutet, dass es zur gleichen Zeit passiert.
3 Siehe Vert.x Reactive Streams Integration für weitere Details.
Get Reaktive Systeme in Java now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.