Heim > Java > javaLernprogramm > Hauptteil

Warum haben wir die reaktive Systemarchitektur aus unserem Code verworfen?

王林
Freigeben: 2024-08-30 06:00:35
Original
973 Leute haben es durchsucht

In diesem Artikel geht es um unsere Entscheidung, in unserem Softwareprojekt von der reaktiven Architektur abzuweichen. Wir werden uns mit den Grundprinzipien reaktiver Systeme, den Vorteilen nicht blockierender E/A und den Herausforderungen befassen, denen wir mit einem reaktiven Ansatz gegenüberstanden.

Verständnis des reaktiven Architekturstils

Reactive umfasst eine Reihe von Prinzipien und Richtlinien, die auf den Aufbau reaktionsfähiger verteilter Systeme und Anwendungen abzielen, gekennzeichnet durch:

  1. Reaktionsfähigkeit:Fähig, Anfragen auch unter hoher Belastung schnell zu bearbeiten.
  2. Belastbarkeit: Kann sich nach Ausfällen mit minimaler Ausfallzeit erholen.
  3. Elastizität: Kann sich an wechselnde Arbeitslasten anpassen, indem die Ressourcen entsprechend skaliert werden.
  4. Nachrichtengesteuert: Nutzt asynchrone Nachrichten, um die Fehlertoleranz zu verbessern und Komponenten zu entkoppeln.

Ein wesentlicher Vorteil reaktiver Systeme ist die Verwendung nicht blockierender E/A. Dieser Ansatz vermeidet das Blockieren von Threads während E/A-Vorgängen, sodass ein einzelner Thread mehrere Anforderungen gleichzeitig bearbeiten kann. Dies kann die Systemeffizienz im Vergleich zu herkömmlichen blockierenden E/A erheblich verbessern.
Beim herkömmlichen Multithreading stellen Blockierungsoperationen erhebliche Herausforderungen bei der Optimierung von Systemen dar (Abbildung 1). Gierige Anwendungen, die übermäßig viel Arbeitsspeicher verbrauchen, sind ineffizient und benachteiligen andere Anwendungen, was oft die Anforderung zusätzlicher Ressourcen wie Arbeitsspeicher, CPU oder größerer virtueller Maschinen erforderlich macht.

Why we discarded Reactive systems architecture from our code?

Abbildung 1 – Traditionelles Multithreading


E/A-Vorgänge sind ein wesentlicher Bestandteil moderner Systeme und ihre effiziente Verwaltung ist von größter Bedeutung, um gieriges Verhalten zu verhindern. Reaktive Systeme verwenden nicht blockierende E/A, sodass eine geringe Anzahl von Betriebssystem-Threads zahlreiche gleichzeitige E/A-Vorgänge verarbeiten kann.

Reaktives Ausführungsmodell

Obwohl nicht blockierendes I/O erhebliche Vorteile bietet, führt es ein neuartiges Ausführungsmodell ein, das sich von herkömmlichen Frameworks unterscheidet. Zur Behebung dieses Problems wurde eine reaktive Programmierung entwickelt, die die Ineffizienz von Plattform-Threads im Leerlauf während Blockierungsvorgängen verringert (Abbildung 2).

Why we discarded Reactive systems architecture from our code?

Abbildung 2 – Reaktive Ereignisschleife


Quarkus und Reaktiv

Quarkus nutzt eine reaktive Engine, die auf Eclipse Vert.x und Netty basiert und nicht blockierende I/O-Interaktionen ermöglicht. Mutiny, der bevorzugte Ansatz zum Schreiben von reaktivem Code mit Quarkus, übernimmt ein ereignisgesteuertes Paradigma, bei dem Reaktionen durch empfangene Ereignisse ausgelöst werden.

Mutiny bietet zwei ereignisgesteuerte und faule Typen:

  1. Uni: Gibt ein einzelnes Ereignis (ein Element oder einen Fehler) aus, das zur Darstellung asynchroner Aktionen mit null oder einem Ergebnis geeignet ist.
  2. Multi: Gibt mehrere Ereignisse aus (n Elemente, ein Fehler oder ein Abschluss), die möglicherweise unbegrenzte Elementströme darstellen.

Herausforderungen mit Reactive

Während reaktive Systeme Vorteile bieten, sind wir während der Entwicklung auf mehrere Herausforderungen gestoßen:

  • Paradigmenwechsel: Reaktive Programmierung erfordert einen grundlegenden Wandel in der Denkweise der Entwickler, der eine Herausforderung darstellen kann, insbesondere für Entwickler, die an imperative Programmierung gewöhnt sind. Im Gegensatz zu Hilfstools wie der Streams-API erfordert der reaktive Ansatz eine komplette Überarbeitung der Denkweise.
  • Lesbarkeit und Verständnis des Codes: Reaktiver Code bereitet neuen Entwicklern Schwierigkeiten, ihn zu verstehen, was dazu führt, dass mehr Zeit für die Entschlüsselung und das Verständnis aufgewendet wird. Die Komplexität, die durch reaktive Paradigmen entsteht, verschärft dieses Problem.

„Tatsächlich liegt das Verhältnis der Zeit, die mit Lesen und Schreiben verbracht wird, bei weit über 10 zu 1. Wir lesen ständig alten Code, um neuen Code zu schreiben es einfacher zu schreiben.“
Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship

  • Herausforderungen beim Debuggen: Das Debuggen von reaktivem Code erweist sich mit Standard-IDE-Debuggern als nahezu unmöglich, da Lambdas den größten Teil des Codes kapseln. Darüber hinaus erschwert der Verlust aussagekräftiger Stack-Traces bei Ausnahmen die Debugging-Bemühungen zusätzlich. Erhöhter Entwicklungs- und Testaufwand: Die inhärente Komplexität von reaktivem Code kann aufgrund des Zeitaufwands für das Schreiben, Ändern und Testen zu längeren Entwicklungszyklen führen.

Hier ist ein Beispiel für reaktiven Code, der Mutiny verwendet, um die Komplexität zu veranschaulichen:

Multi.createFrom().ticks().every(Duration.ofSeconds(15))
    .onItem().invoke(() - > Multi.createFrom().iterable(configs())
    .onItem().transform(configuration - > {
  try {
    return Tuple2.of(openAPIConfiguration,
        RestClientBuilder.newBuilder()
            .baseUrl(new URL(configuration.url()))
            .build(MyReactiveRestClient.class)
            .getAPIResponse());

  } catch (MalformedURLException e) {
    log.error("Unable to create url");

  }
  return null;
}).collect().asList().toMulti().onItem().transformToMultiAndConcatenate(tuples - > {

  AtomicInteger callbackCount = new AtomicInteger();
  return Multi.createFrom().emitter(emitter - > Multi.createFrom().iterable(tuples)
      .subscribe().with(tuple - >
          tuple.getItem2().subscribe().with(response - > {
              emitter.emit(callbackCount.incrementAndGet());

  if (callbackCount.get() == tuples.size()) {
    emitter.complete();
  }
                    })
                ));

}).subscribe().with(s - > {},
Throwable::printStackTrace, () - > doSomethingUponComplete()))
    .subscribe().with(aLong - > log.info("Tic Tac with iteration: " + aLong));
Nach dem Login kopieren

Zukunftsausblick – Projekt Loom und darüber hinaus

Project Loom, eine aktuelle Entwicklung im Java-Ökosystem, verspricht, die mit Blockierungsvorgängen verbundenen Probleme zu mildern. Durch die Möglichkeit der Erstellung Tausender virtueller Threads ohne Hardwareänderungen könnte Project Loom in vielen Fällen möglicherweise die Notwendigkeit eines reaktiven Ansatzes überflüssig machen.

„Project Loom wird die reaktive Programmierung töten“
Brian Goetz

Abschluss

Zusammenfassend lässt sich sagen, dass unsere Entscheidung, vom reaktiven Architekturstil abzuweichen, ein pragmatischer Ansatz für die langfristige Wartbarkeit unseres Projekts ist. Während reaktive Systeme potenzielle Vorteile bieten, überwogen die Herausforderungen, die sie für unser Team darstellten, diese Vorteile in unserem spezifischen Kontext.

Wichtig ist, dass diese Verschiebung die Leistung nicht beeinträchtigte. Dies ist ein positives Ergebnis, da es zeigt, dass eine gut konzipierte nicht reaktive (imperative) Architektur die erforderliche Leistung liefern kann, ohne die Komplexität, die in unserem Fall mit einer reaktiven Architektur verbunden ist.

Wenn wir in die Zukunft blicken, liegt der Schwerpunkt weiterhin auf dem Aufbau einer Codebasis, die nicht nur funktional, sondern auch für Entwickler aller Erfahrungsstufen leicht zu verstehen und zu warten ist. Dies verkürzt nicht nur die Entwicklungszeit, sondern fördert auch eine bessere Zusammenarbeit und den Wissensaustausch innerhalb des Teams.

In der folgenden Grafik stellt die X-Achse die zunehmende Komplexität unserer Codebasis im Laufe ihrer Entwicklung dar, während die Y-Achse die Zeit darstellt, die für diese Entwicklungsänderungen erforderlich ist.

Why we discarded Reactive systems architecture from our code?

Das obige ist der detaillierte Inhalt vonWarum haben wir die reaktive Systemarchitektur aus unserem Code verworfen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage