Wie ereignisgesteuerte Architektur die Herausforderungen moderner Webanwendungen löst

Hallo Habr!







Während unser Verkauf für die anspruchsvollsten Geschmäcker fortgesetzt wird , lenken wir Ihre Aufmerksamkeit auf ein anderes Thema unserer kreativen Suche: Event-Driven Architecture (EDA). Unter dem Schnitt finden Sie wunderschöne Flussdiagramme und eine Geschichte darüber, wie dieses innovative Paradigma bei der Entwicklung von Webanwendungen hilft.



In diesem Artikel werden einige der Herausforderungen untersucht, die Innovationen in der modernen Webentwicklung vorantreiben. Als Nächstes werden wir uns mit der ereignisgesteuerten Architektur (EDA) befassen, die diese Probleme durch eine Neudefinition der Serverarchitektur behebt.



Webanwendungen haben seit den Tagen, als statischer HTML-Inhalt von einem Server bereitgestellt wurde, einen langen Weg zurückgelegt. Heutzutage sind Webanwendungen viel komplexer geworden und verwenden eine Vielzahl von Frameworks, Rechenzentren und Technologien. In den letzten Jahren sind zwei Trends zu beobachten, die die Entwicklung des IT-Marktes bestimmen:



  • Übertragen von Anwendungen in die Cloud ;
  • Implementierung der Microservice- Architektur.


Diese Ideen bestimmen maßgeblich, wie Software heute entworfen und gebaut wird. Wir können sagen, dass wir heute keine Anwendungen mehr erstellen, sondern Plattformen. Anwendungen belegen keinen gemeinsam genutzten Speicherplatz mehr. Stattdessen müssen sie Informationen über einfache Kommunikationsprotokolle wie REST-APIs oder Remote Procedure Calls (RPC) miteinander austauschen. Dieses Modell hat zu großartigen Produkten wie Facebook, Netflix, Uber und mehr geführt.

In diesem Artikel werden einige der Herausforderungen untersucht, die Innovationen in der modernen Webentwicklung vorantreiben. Als Nächstes werden wir uns mit der ereignisgesteuerten Architektur (Event-Driven Architecture, EDA) befassen, um diesen Herausforderungen durch eine Neudefinition der Serverarchitektur zu begegnen.



Aktuelle Probleme des modernen Web



Jede Web-Technologie muss die Herausforderungen bewältigen, denen sich moderne asynchrone Mehrbenutzeranwendungen stellen müssen, um reibungslos zu funktionieren:



Verfügbarkeit



Jetzt arbeiten wir nicht mit einer Anwendung, sondern mit vielen - Dutzenden oder sogar Hunderten - verwandten Diensten, und jeder von ihnen muss seine Probleme sieben Tage die Woche rund um die Uhr lösen. Wie kann dies erreicht werden? In den meisten Fällen wird der Dienst horizontal auf mehrere Instanzen skaliert, die auf mehrere Rechenzentren verteilt werden können, um eine hohe Verfügbarkeit sicherzustellen. Alle Anforderungen für diesen bestimmten Dienst werden weitergeleitet und gleichmäßig auf alle Instanzen verteilt. Einige Bereitstellungstools bieten Selbstheilungsfunktionen. Wenn also eine Instanz ausfällt, wird eine andere erstellt, um ihren Platz einzunehmen.



Skalierbarkeit



Die Skalierbarkeit entspricht in vielerlei Hinsicht der Verfügbarkeit. Die Barrierefreiheit besteht im Wesentlichen darin, sicherzustellen, dass mindestens eine Instanz des Dienstes betriebsbereit ist und eingehende Anforderungen bedienen kann. Die Skalierbarkeit hängt wiederum hauptsächlich von der Leistung ab. Wenn eine Anwendung überladen ist, werden neue Instanzen dieser Anwendung erstellt, um die erhöhte Anzahl von Anforderungen zu berücksichtigen. Die vertikale Skalierung von Anwendungen ist jedoch keine triviale Aufgabe, insbesondere bei statusbehafteten Anwendungen .



Eine Quelle der Wahrheit



Vor dem Aufkommen von Microservices war dies eine ziemlich einfache Aufgabe. Alle Daten befanden sich an einem Ort, in der Regel war es die eine oder andere relationale Datenbank. Wenn jedoch mehrere Dienste eine Datenbank gemeinsam nutzen, können Probleme wie Abhängigkeiten zwischen verschiedenen Teams in Bezug auf Schemaänderungen oder Leistungsprobleme auftreten. Normalerweise wurde dieses Problem gelöst, indem jedem Dienst eine eigene Datenbank zugewiesen wurde. Eine verteilte Wahrheitsquelle ist sehr hilfreich bei der Aufrechterhaltung einer sauberen Architektur. In einer solchen Situation müssen Sie sich jedoch mit verteilten Transaktionen und der Komplexität der Unterstützung mehrerer Datenbanken auseinandersetzen.



Synchronizität



In einem typischen Request-Response-Szenario wartet der Client auf die Antwort des Servers. Es blockiert alle Aktionen, bis es eine Antwort erhält oder bis die angegebene Verzögerung abläuft. Wenn Sie dieses Verhalten mithilfe von Aufrufketten, die das gesamte System durchlaufen, in eine Microservice-Architektur implementieren, können Sie sich leicht in der sogenannten "Microservice-Hölle" wiederfinden. Alles beginnt mit einem Anruf bei nur einem Dienst. Nennen wir ihn "Dienst A". Aber dann muss Service A Service B anrufen, und der Spaß beginnt. Das Problem bei diesem Verhalten ist folgendes: Wenn der Dienst selbst blockierten Ressourcen zugeordnet ist (z. B. ein Thread hängt), nehmen die Verzögerungen exponentiell zu. Wenn wir eine Verzögerung von 500 ms pro Dienst zulassen und fünf Dienstaufrufe in der Kette vorhanden sind, benötigt der erste Dienst eine Verzögerung von 2500 ms (2,5 Sekunden) und der letzte eine Verzögerung von 500 ms.







Die Herausforderungen des modernen Web



Einführung in die ereignisgesteuerte Architektur



Event-Driven Architecture (EDA) ist ein Paradigma für Softwarearchitekturen, das die Generierung, Entdeckung, den Verbrauch von Ereignissen und die Reaktion darauf erleichtert.




In klassischen dreistufigen Anwendungen ist die Datenbank der Kern des Systems. In EDA verlagert sich der Fokus auf Ereignisse und wie sie durch das System gefiltert werden. Diese Verschiebung des Fokus ermöglicht es uns, die Art und Weise, wie wir Anwendungen entwerfen, vollständig zu ändern und die oben genannten Probleme zu lösen.



Bevor wir uns genau ansehen, wie dies in EDA gemacht wird, schauen wir uns an, was ein "Ereignis" ist. Ein Ereignis ist eine Aktion, die entweder eine Benachrichtigung oder eine Änderung des Status der Anwendung auslöst. Das Licht ging an (Benachrichtigung), der Thermostat schaltete die Heizung aus (Benachrichtigung), der Benutzer änderte seine Adresse (Statusänderung), einer Ihrer Freunde änderte seine Telefonnummer (Statusänderung). Dies sind alles Ereignisse, aber es ist noch keine Tatsache, dass wir sie einer ereignisgesteuerten Lösung hinzufügen sollten. Es wird davon ausgegangen, dass der Architektur nur geschäftsrelevante Ereignisse hinzugefügt werden. Das Ereignis "Benutzer gibt eine Bestellung auf" ist aus geschäftlicher Sicht wichtig, "Benutzer isst eine bestellte Pizza oder ein Mittagessen" jedoch nicht.



Wenn Sie an einige Ereignisse denken, dann ist bei einigen sofort klar, dass sie für das Geschäft wichtig sind, und bei einigen - nicht. Besonders über diejenigen, die als Reaktion auf andere Ereignisse auftreten. Eine als " Ereignisangriff " bezeichnete Technik wird verwendet, um Ereignisse zu identifizieren, die das System durchlaufen . Die Teilnehmer an der Entwicklung der Anwendung (von Programmierern über Entwickler von Geschäftslogik bis hin zu Experten auf dem Fachgebiet) werden einberufen und bilden alle Geschäftsprozesse gemeinsam ab und präsentieren sie in Form spezifischer Ereignisse. Wenn eine solche Karte fertig ist, wird das Ergebnis der Arbeit in Form von Anforderungen formuliert, die bei der Entwicklung von Anwendungen erfüllt werden müssen.







Ein Beispiel für einen Buchungsantrag, der durch die Event-Angriffsmethode beschrieben wird



Nachdem wir die für uns interessanten Ereignisse identifiziert und entschieden haben, wie sie identifiziert werden sollen, schauen wir uns an, wie dieses Paradigma die oben genannten typischen Probleme lösen kann.



Der Ablauf der Ereignisse ist unidirektional: vom Produzenten zum Verbraucher. Vergleichen Sie diese Situation mit einem REST-Aufruf. Der Eventproduzent erwartet grundsätzlich keine Antwort vom Verbraucher, während im Falle eines REST-Aufrufs immer eine Antwort erfolgt. Keine Antwort bedeutet, dass die Ausführung des Codes nicht blockiert werden muss, bis etwas anderes passiert. In diesem Fall werden Ereignisse asynchroner Natur, wodurch das Risiko von Verzögerungen vollständig beseitigt wird.



Ereignisse treten als Ergebnis einer Aktion auf, sodass es kein Zielsystem gibt. Von Service A kann nicht gesagt werden, dass er Ereignisse für Service B auslöst. Wir können jedoch sagen, dass Dienst B an den von Dienst A erzeugten Ereignissen interessiert ist. Zwar kann es in diesem System andere "interessierte Parteien" geben, z. B. Dienste C oder D.



Wie können wir sicherstellen, dass ein in einem bestimmten System initiiertes Ereignis alle erreicht? "Interessierte" Dienstleistungen? Typischerweise werden solche Systeme unter Verwendung von Nachrichtenbrokern gelöst. Ein Broker ist einfach eine Anwendung, die als Vermittler zwischen dem Ereignisemitter (der Anwendung, die das Ereignis generiert hat) und dem Ereigniskonsumenten fungiert. Auf diese Weise können Anwendungen sauber voneinander getrennt werden, um das Problem der Barrierefreiheit zu lösen, was oben in diesem Beitrag besprochen wurde. Wenn die Anwendung derzeit nicht verfügbar ist, werden bei der Online-Rückkehr Ereignisse verarbeitet und verarbeitet, um alle Ereignisse auszugleichen, die während des Zeitraums aufgetreten sind, in dem sie nicht verfügbar waren.



Was ist mit Data Warehouse? Können Ereignisse in einer Datenbank gespeichert werden oder ist anstelle einer Datenbank etwas anderes erforderlich? Natürlich können Ereignisse in Datenbanken gespeichert werden, aber in diesem Fall geht ihre "Ereignis" -Eigenschaft verloren. Sobald ein Ereignis aufgetreten ist, können wir es nicht mehr korrigieren, daher sind Ereignisse von Natur aus unveränderlich. Datenbanken wiederum ... können geändert werden. Nach Eingabe der Daten in die Datenbank können sie geändert werden.



Besser speichern Ereignisse in Ereignisprotokollen . Ereignisprotokolle sind nichts anderes als zentralisiertData Warehouse, bei dem jedes Ereignis als Folge unveränderlicher Datensätze aufgezeichnet wird, das sogenannte "Protokoll". Ein Protokoll kann mit einem Protokoll verglichen werden, bei dem jedes neue Ereignis am Ende der Liste hinzugefügt wird. Sie können jederzeit den aktuellsten Status wiederherstellen, indem Sie alle Protokollereignisse vom Anfang bis zur Gegenwart wiedergeben.



Wir haben also alle Probleme außer der Skalierbarkeit behandelt. Ereignisgesteuerte Dienste sind immer so konzipiert, dass sie über mehrere Instanzen hinweg bereitgestellt werden. Da der Status als solcher im Ereignisprotokoll gespeichert ist, ist der Dienst selbst zustandslos, was eine chirurgisch genaue Skalierung aller interessierenden Dienste ermöglicht.



Die einzige Ausnahme von diesem Prinzip sind Dienste, mit denen materialisierte Ansichten erstellt werden sollen.... Im Wesentlichen ist eine materialisierte Ansicht ein Status, der ein Ereignisprotokoll zu einem bestimmten Zeitpunkt beschreibt. Dieser Ansatz wird verwendet, um das Abfragen von Daten zu vereinfachen. Zurück zum Thema Skalierung: Eine materialisierte Ansicht ist einfach eine aggregierte Ansicht von Ereignissen in Form einer Tabelle. aber wo lagern wir diese Tabellen? In den meisten Fällen werden solche Aggregationen im Speicher angezeigt, und gleichzeitig wird unser Service automatisch zu einem zustandsbehafteten. Eine schnelle und einfache Lösung besteht darin, für jeden Dienst, der materialisierte Ansichten erstellt, eine lokale Datenbank bereitzustellen. Auf diese Weise wird der Status in der Datenbank gespeichert und der Dienst wird zustandslos ausgeführt.







Obwohl es ereignisgesteuerte Architektur seit über 15 Jahren gibt, hat sie erst vor kurzem ernsthafte Popularität erlangt, und dies ist kein Zufall. Die meisten Unternehmen durchlaufen eine Phase der " digitalen Transformation ", die von wilden Anforderungen begleitet wird. Aufgrund der Komplexität dieser Anforderungen müssen Ingenieure neue Ansätze für das Software-Design beherrschen, was insbesondere bedeutet, dass der Zusammenhalt der Dienste untereinander geschwächt und die Kosten für die Wartung der Dienste gesenkt werden. EDA ist eine mögliche Lösung für diese Probleme, aber nicht die einzige. Erwarten Sie auch nicht, dass alle Probleme gelöst werden, Sie müssen nur zu EDA wechseln. Für einige Funktionen sind möglicherweise noch robuste, altmodische REST-APIs oder das Speichern von Informationen in einer Datenbank erforderlich. Wählen Sie die für Sie am besten geeignete und gestalten Sie sie richtig!



All Articles