
Die Welt steht nicht still. Der Fortschritt schafft neue technologische Herausforderungen. Mit den sich ändernden Anforderungen muss sich auch die Architektur der Informationssysteme weiterentwickeln. Heute werden wir über ereignisorientierte Architektur, Konkurrenz, Parallelität, Asynchronität und darüber sprechen, wie man in Erlang friedlich damit leben kann.
Einführung
Je nach Größe des geplanten Systems und den Anforderungen daran wählen wir Entwickler die Methode zur Informationsübertragung im System aus. In den meisten Fällen kann ein Broker-basierendes Schema, beispielsweise auf RabbitMQ oder Kafka, eine praktikable Lösung zur Organisation der Interaktion der Dienste sein. Aber manchmal sind der Ereignisfluss, die SLA und der Kontrollgrad über das System so beschaffen, dass uns bestehende Messaging-Systeme nicht ausreichen. Natürlich kann man das System etwas komplexer gestalten, indem man die Verantwortung für die Transportschicht und die Clusterbildung übernimmt, zum Beispiel mit ZeroMQ oder nanomsg. Aber wenn das System über ausreichende Bandbreite und Funktionen des standardmäßigen Erlang-Clusters verfügt, erfordert die Einfügung einer zusätzlichen Entität eine detaillierte Untersuchung und wirtschaftliche Rechtfertigung.
Das Thema reaktive verteilte Anwendungen ist recht umfangreich. Um im Format eines Artikels zu bleiben, wird sich die heutige Diskussion nur auf homogene Umgebungen konzentrieren, die auf Erlang/Elixir basieren. Das Ökosystem Erlang/OTP ermöglicht die Implementierung einer reaktiven Architektur mit minimalem Aufwand. Aber in jedem Fall benötigen wir eine Kommunikationsschicht.
Theoretische Grundlagen
Das Design beginnt mit der Definition von Zielen und Beschränkungen. Das Hauptziel liegt nicht im Bereich der Entwicklung um der Entwicklung willen. Wir benötigen ein sicheres und skalierbares Werkzeug, auf dessen Grundlage moderne Anwendungen unterschiedlichen Niveaus erstellt werden können und, was am wichtigsten ist, weiterentwickelt werden können: beginnend bei Ein-Server-Anwendungen, die eine kleine Zielgruppe bedienen und sich später zu Clustern von bis zu 50-60 Knoten entwickeln können, bis hin zu Föderationen von Clustern. Daher besteht das Hauptziel darin, den Gewinn durch Senkung der Entwicklungskosten und der Eigentumskosten des Endsystems zu maximieren.
Lassen Sie uns vier Hauptanforderungen an das Endsystem hervorheben:
- CEreignisorientierung.
Das System ist stets bereit, einen Strom von Ereignissen zu verarbeiten und die erforderlichen Maßnahmen zu ergreifen; - Maschinenfähigkeit.
Einzelblöcke können sowohl vertikal als auch horizontal skaliert werden. Das gesamte System sollte in der Lage sein, unbegrenzt horizontal zu wachsen; - Ordnungssicherheit.
Alle Ebenen und alle Dienste müssen in der Lage sein, sich bei Ausfällen automatisch wiederherzustellen; - Garantierte Reaktionszeit.
Zeit ist wertvoll, und Benutzer sollten nicht zu lange warten müssen.
Erinnern Sie sich an das alte Märchen über "Die kleine Lokomotive, die es konnte"? Damit das entstehende System erfolgreich aus der Prototyp-Phase herauskommt und fortschrittlich ist, muss sein Fundament die Mindestanforderungen erfüllen. KONNTE.
Dem Messaging als Infrastrukturwerkzeug und Basis für alle Dienste wird ein weiterer Punkt hinzugefügt: Benutzerfreundlichkeit für Programmierer.
Ereignisorientierung
Damit die Anwendung von einer Server zu einem Cluster wachsen kann, muss ihre Architektur eine schwache Kopplung gewährleisten. Dieses Kriterium erfüllt das asynchrone Modell. Darin kümmern sich Sender und Empfänger um die Informationslast der Nachricht und machen sich keine Gedanken über Übertragung und Routing innerhalb des Systems.
Skalierbarkeit
Skalierbarkeit und Effizienz des Systems stehen in engem Zusammenhang. Die Anwendungsbestandteile müssen in der Lage sein, alle verfügbaren Ressourcen zu nutzen. Je effektiver wir die Kapazitäten nutzen können und je optimierter unsere Verarbeitungsmethoden sind, desto weniger Geld geben wir für Hardware aus.
Innerhalb einer Maschine schafft Erlang eine hochkonkurrierende Umgebung. Das Gleichgewicht zwischen Konkurrenz und Parallelität kann durch die Auswahl der Anzahl der Betriebssystemthreads, die für die Erlang-VM verfügbar sind, und der Anzahl der Scheduler, die diese Threads nutzen, bestimmt werden.
Erlang-Prozesse haben keinen gemeinsamen Zustand und arbeiten im nicht-blockierenden Modus. Dies ermöglicht eine vergleichsweise niedrige Latenz und eine höhere Durchsatzrate als traditionelle Anwendungen, die auf blockierender Synchronisation basieren. Der Erlang-Scheduler sorgt für eine faire Verteilung von CPU und IO, und das Fehlen von Sperren ermöglicht es der Anwendung, selbst in Spitzenlastzeiten oder bei Ausfällen zu reagieren.
Auf Clusterebene besteht ebenfalls ein Problem mit der Ressourcennutzung. Es ist wichtig, dass alle Maschinen im Cluster gleichmäßig ausgelastet sind und das Netzwerk nicht überlastet wird. Stellen wir uns eine Situation vor: Der Nutzerverkehr landet bei den eingehenden Load Balancern (haproxy, nginx usw.), die die Anfragen möglichst gleichmäßig auf eine Reihe verfügbarer Backends verteilen. Innerhalb der Anwendungsinfrastruktur ist der Dienst, der die erforderliche Schnittstelle bereitstellt, nur die letzte Meile, und er muss eine Reihe anderer Dienste anfragen, um die ursprüngliche Anfrage zu beantworten. Interne Anfragen erfordern ebenfalls Routing und Lastverteilung.
Um Datenströme effektiv zu verwalten, sollte Messaging den Entwicklern eine Schnittstelle zur Verfügung stellen, um das Routing und die Lastverteilung zu steuern. Dadurch können die Entwickler mithilfe von Mikroservice-Architekturen (Aggregator, Proxy, Chain, Branch usw.) sowohl Standardaufgaben als auch seltene Probleme lösen.
Aus geschäftlicher Sicht ist Skalierbarkeit eines der Instrumente des Risikomanagements. Das Hauptziel ist es, die Anforderungen der Kunden zu erfüllen und dabei die Hardware optimal zu nutzen:
- Durch die Steigerung der Hardwareleistung infolge des Fortschritts wird diese nicht aufgrund von Softwareunzulänglichkeiten ungenutzt bleiben. Erlang lässt sich hervorragend vertikal skalieren und kann immer alle CPU-Kerne und den verfügbaren Speicher auslasten;
- In Bezug auf Cloud-Umgebungen können wir die Menge der Hardware je nach aktueller oder vorhergesagter Last verwalten und SLA garantieren.
Fehlertoleranz
Betrachten wir zwei Axiome: „Ausfälle sind nicht akzeptabel“ und „Ausfälle werden immer vorkommen“. Für das Geschäft bedeutet ein Softwareausfall Geldverlust und, was noch schlimmer ist, einen Reputationsverlust. Indem man zwischen möglichen Verlusten und den Kosten für die Entwicklung ausfallsicherer Software balanciert, findet man oft einen Kompromiss.
Kurzfristig spart eine Architektur, die die Ausfallsicherheit berücksichtigt, Geld beim Kauf fertiger Clusterlösungen. Diese sind teuer und enthalten ebenfalls Fehler.
Langfristig amortisiert sich eine ausfallsichere Architektur vielfach in allen Phasen der Entwicklung.
Die Messaging-Funktion innerhalb des Codes befindet sich noch in der Entwicklungsphase und ermöglicht eine detaillierte Ausarbeitung der Interaktion der Komponenten innerhalb des Systems. Dadurch wird die Aufgabe der Reaktion und des Fehlermanagements vereinfacht, da alle verantwortlichen Komponenten Fehler verarbeiten und das Gesamtsystem weiß, wie es nach einem Fehler automatisch zum Normalzustand zurückkehren kann, gemäß dem Design.
Reaktionsfähigkeit
Unabhängig von Fehlern muss die Anwendung auf Anfragen reagieren und die SLA erfüllen. Die Realität ist, dass die Menschen nicht warten möchten, daher muss sich das Geschäft anpassen. Von immer mehr Anwendungen wird hohe Reaktionsfähigkeit erwartet.
Reaktionsfähige Anwendungen arbeiten in einem nahezu Echtzeitmodus. Die Erlang VM funktioniert im Modus der weichen Echtzeit. Für bestimmte Bereiche wie den Börsenhandel, die Medizin und das Management von Industrieanlagen ist der Modus der harten Echtzeit wichtig.
Reaktionsfähige Systeme verbessern das Benutzererlebnis und sind für Unternehmen nützlich.
Vorläufiges Ergebnis
Bei der Planung dieses Artikels wollte ich meine Erfahrungen beim Erstellen eines Nachrichtenaustausch-Brokers und beim Aufbau komplexer Systeme darauf basierend teilen. Aber der theoretische und motivationale Teil wurde ziemlich umfangreich.
Im zweiten Teil des Artikels werde ich über die Feinheiten der Implementierung von Austauschpunkten, Austauschmustern und deren Anwendung sprechen.
Im dritten Teil werden wir allgemeine Fragen zur Organisation von Diensten, zur Routenführung und zur Lastverteilung betrachten. Wir werden über die praktische Seite der Skalierbarkeit und Fehlertoleranz von Systemen sprechen.
Ende des ersten Teils.
Foto .
Quelle: habr.com
