Es gibt
viele Arten von Softwarearchitekturen mit ihren Vor- und Nachteilen. Als nächstes werden wir über die Funktionen der beliebtesten von ihnen sprechen und über unseren Übergang zu Microservices.
/ libreshot / PDArten von Softwarearchitekturen
Schichtarchitektur
Dies ist eine der häufigsten Architekturen. Auf dieser Basis werden viele große Frameworks erstellt - Java EE, Drupal, Express. Das vielleicht bekannteste Beispiel für diese Architektur ist das
OSI- Netzwerkmodell.
Das System ist in Ebenen unterteilt, von denen jede nur mit zwei benachbarten interagiert. Daher werden Abfragen an die Datenbank, die sich normalerweise ganz am Ende der Interaktionskette befindet, nacheinander durch jede „Schicht“ geleitet.
Architektur
impliziert keine obligatorische Anzahl von Ebenen - es kann drei, vier, fünf oder mehr geben. Am häufigsten werden dreistufige Systeme verwendet: mit einer Präsentationsebene (Client), einer Logikebene und einer Datenebene.
Es wurden unzählige Bücher und Artikel über Mehrebenenarchitektur geschrieben. Und es gab unterschiedliche Meinungen über seine Vor- und Nachteile.
Vorteile:Jede Ebene dieser Architektur führt einen streng begrenzten Satz von Funktionen aus (die nicht von Schicht zu Schicht wiederholt werden) und weiß nicht, wie die anderen Ebenen angeordnet sind. Daher kann der „Inhalt“ von Ebenen geändert werden, ohne dass das Risiko globaler Konflikte zwischen Ebenen besteht.
Im Allgemeinen sind mehrstufige Anwendungen so weit verbreitet, dass spezielle Vorlagengeneratoren für ihre Entwicklung erstellt werden. Beispielsweise bietet
LASG für Visual Studio verschiedene Methoden zur Codegenerierung, mit denen Routineaufgaben automatisiert und Anwendungsebenen erstellt werden können.
Nachteile:In der Programmierung gibt es ein Sprichwort, dass jedes Problem durch Hinzufügen einer weiteren Abstraktionsebene gelöst werden kann. Dieser Ansatz kann jedoch letztendlich zu einer schlechten Organisation des Codes führen und Entwickler verwirren.
Ein weiteres Problem ergibt sich daraus - niedrige Geschwindigkeit. Viele Informationen werden ohne Verwendung von Geschäftslogik nutzlos von Schicht zu Schicht weitergegeben. Dieses Problem
wird manchmal
als Sinkhole-Anti-Pattern bezeichnet, ein Entwurfsmuster, bei dem die Anzahl der nutzlosen Operationen die nützlichen überwiegt.
Das Auffinden von Fehlern auf mehrschichtigen Systemen
kann ebenfalls
schwierig sein . Vor dem Betreten der Datenbank durchlaufen die Informationen alle Ebenen (da die Datenbank die letzte Komponente ist). Wenn diese Informationen aus irgendeinem Grund beschädigt sind (oder unterwegs verloren gehen), müssen Sie jede Ebene separat analysieren, um einen Fehler zu finden.
Gute Passform:- So erstellen Sie neue Anwendungen, die schnell bereitgestellt werden müssen. Dies ist eine Art "Allzweckvorlage".
Als wir in 1cloud mit der Arbeit an den internen Systemen unseres Anbieters für virtuelle Infrastruktur begannen , verwendeten wir diese spezielle Art von Architektur. Zu Beginn hatten wir nicht die Aufgabe, einen IaaS-Dienst zu erstellen, der den Datenverkehr von Zehntausenden oder Hunderttausenden von Benutzern verarbeiten kann. Wir haben uns entschlossen, das Produkt schnell auf den Markt zu bringen und mit der Entwicklung eines Kundenstamms zu beginnen und die Skalierungsprobleme zu lösen, sobald sie verfügbar sind (und jetzt übertragen wir alle Systeme auf eine Microservice-Architektur, die später erläutert wird).
Unter den Entwicklern gibt es die Meinung, dass es nicht von den ersten Tagen des Projekts an notwendig ist, es auf kolossale Belastungen vorzubereiten (zukunftssichere Software schreiben). Die tatsächlichen Anforderungen an die Anwendung oder den Dienst können von den Erwartungen abweichen, und die Geschäftsziele können sich ändern . Code, der mit Blick auf die ferne Zukunft geschrieben wurde, kann daher zu einer technischen Schuld werden. - Laut O'Reilly ist die Schichtarchitektur für viele Unternehmensanwendungen eine natürliche Wahl. Da Unternehmen (insbesondere große) häufig Kompetenzen teilen: Es gibt ein Team, das für das Front-End verantwortlich ist, es gibt Personen, die für das Back-End verantwortlich sind, und so weiter. Dies impliziert die natürliche Aufteilung von Anwendungen in Ebenen: Einige Entwickler arbeiten am Client, andere an der Logik.
Eine ähnliche Beziehung zwischen der Struktur der Organisation und den Ansätzen zur Anwendungsentwicklung wird auch durch das 1967 formulierte Conway-Gesetz vorgegeben . Darin heißt es: „Bei der Entwicklung eines Systems sind Unternehmen gezwungen, sich an ein Schema zu halten, das die Kommunikationsstruktur innerhalb des Unternehmens wiederholt.“
Ereignisorientierte Architektur
In diesem Fall schreibt der Entwickler Verhalten (Reaktionen) für das Programm vor, wenn Ereignisse auftreten. Ein Ereignis im System wird als signifikante Änderung seines Zustands angesehen.
Sie können eine Analogie zum Kauf eines Autos in der Kabine ziehen. Wenn ein Auto einen neuen Besitzer findet, ändert sich sein Zustand von "zum Verkauf" zu "verkauft". Diese Veranstaltung startet den Vorbereitungsprozess für den Vorverkauf - Installation zusätzlicher Geräte, Überprüfung des technischen Zustands, Waschen usw.
Ein ereignisgesteuertes System enthält normalerweise zwei Komponenten: Ereignisquellen (Agenten) und deren Verbraucher (Senken). Normalerweise gibt es auch zwei Arten von Ereignissen: ein auslösendes Ereignis und ein Ereignis, auf das Verbraucher reagieren.
Ein Beispiel für die Implementierung einer solchen Architektur ist die Java Swing-Bibliothek. Wenn die Klasse eine Warnung zu einem Ereignis benötigt, implementiert der Entwickler den sogenannten Listener - ActionListener (er "fängt" das entsprechende Ereignis ab) und hängt ihn an das Objekt an, das dieses Ereignis generieren kann.
Der folgende Implementierungscode für diesen Mechanismus wird im Wiki bereitgestellt:
public class FooPanel extends JPanel implements ActionListener { public FooPanel() { super(); JButton btn = new JButton("Click Me!"); btn.addActionListener(this); this.add(btn); } @Override public void actionPerformed(ActionEvent ae) { System.out.println("Button has been clicked!"); } }
Vorteile der Architektur:Da Anwendungen aus einer großen Anzahl von asynchronen Modulen bestehen (die keine Informationen über die Implementierung des jeweils anderen enthalten), sind sie einfach zu skalieren. Solche Systeme werden als Konstruktor zusammengestellt - Sie müssen keine Abhängigkeiten registrieren, sondern nur ein neues Modul implementieren. Darüber hinaus ermöglicht das asynchrone Modell eine hohe Anwendungsleistung.
Nachteile:Die Asynchronität solcher Anwendungen erschwert das Debuggen. Ein Ereignis kann mehrere Aktionsketten gleichzeitig auslösen. Wenn es viele solcher Ketten gibt,
kann es schwierig sein zu verstehen, was genau den Fehler verursacht hat. Um das Problem zu lösen, müssen wir die schwierigen Bedingungen für die Fehlerbehandlung herausarbeiten. Ab hier folgt das Problem mit der Protokollierung - Protokolle sind
schwer zu strukturieren.
Geeignet für:- Erstellung von asynchronen Systemen. Dies ist offensichtlich, da die Architektur selbst aus einer großen Anzahl von asynchronen Modulen besteht.
- Kann zum Erstellen einer Benutzeroberfläche verwendet werden. Eine Webseite fungiert als Container, in dem jede ihrer Komponenten isoliert ist und auf bestimmte Benutzeraktionen reagiert.
- Organisieren von Nachrichten zwischen verschiedenen Informationssystemen.
Mikrokernel-Architektur
Diese Art von Architektur besteht aus zwei Komponenten: dem Kern des Systems und den Plugins. Plugins sind für die Geschäftslogik verantwortlich, und der Kernel verwaltet das Laden und Entladen.
Als Beispiel für die Mikrokernel-Architektur bietet das O'Reilly-Buch
eine Eclipse-IDE. Dies ist ein einfacher Editor, der Dateien öffnet, bearbeitet und Hintergrundprozesse ausführt. Mit Plugins (z. B. dem Java-Compiler) wird die Funktionalität erweitert.
Die Mikrokernel-Architektur
verwendete einst das Symbian-Betriebssystem für mobile Geräte (die Entwicklung wurde 2012 eingestellt). In ihrem Mikrokernel befanden sich ein Taskplaner, Speicherverwaltungssysteme und Treiber, und das Dateisystem und die für die Telefonkommunikation verantwortlichen Komponenten fungierten als Plug-Ins.
Vorteile der Architektur:Es ist einfach,
eine Anwendung von einer Umgebung in eine andere zu portieren, da nur der Mikrokernel geändert werden muss. Die Trennung von Richtlinien auf hoher Ebene und Mechanismen auf niedriger Ebene vereinfacht die Systemunterstützung und stellt deren Erweiterbarkeit sicher.
Nachteile:Die Anwendungsleistung wird verringert, wenn Sie zu viele Module anschließen. Es kann jedoch
problematisch sein, ein Gleichgewicht zwischen der Anzahl der Plugins und der Anzahl der Mikronukleus-Aufgaben zu finden (normalerweise enthält es nur häufig verwendeten Code).
Es ist auch schwierig, den optimalen Fragmentierungsgrad des Mikronukleuscodes im Voraus (vor der Entwicklung der Anwendung) zu bestimmen. Und eine spätere Änderung des Ansatzes ist fast unmöglich.
Gut für:- Erstellen Sie erweiterbare Anwendungen, die von einer großen Anzahl von Personen verwendet werden. Zum Beispiel hat das iPhone-Betriebssystem „Mikrokernel“ -Wurzeln - seine Entwickler haben sich von Mach inspirieren lassen (dies ist eines der ersten Beispiele für einen Mikrokernel).
- Erstellung von Anwendungen mit einer klaren Trennung von grundlegenden Methoden und allgemeinen Regeln.
- Entwicklung von Systemen mit sich dynamisch ändernden Regeln, die häufig aktualisiert werden müssen.
Microservices
Ähnlich wie bei ereignisgesteuerter Architektur und Mikrokernel. Sie werden jedoch verwendet, wenn einzelne Anwendungsaufgaben leicht in kleine Funktionen unterteilt werden können -
unabhängige Dienste . Diese Dienste können in verschiedenen Programmiersprachen geschrieben werden, da sie über die REST-API (z. B.
JSON oder
Thrift ) miteinander kommunizieren.
In welchen Anteilen der Code aufgeteilt ist, entscheidet der Entwickler. Sam Newman, der Autor des Buches „
Erstellen von Microservices “, empfiehlt jedoch, dem Microservice so viele Codezeilen zuzuweisen, wie das Team in zwei Wochen reproduzieren kann. Dies werde es ihm ermöglichen, ein übermäßiges "Aufblähen" der Architektur zu vermeiden.
Am häufigsten werden Microservices in sogenannten Containern gestartet. Diese Container sind über das Netzwerk für andere Microservices und Anwendungen zugänglich, und das Orchestrierungssystem verwaltet sie alle: Beispiele hierfür sind Kubernetes, Docker Swarm usw.
Vorteile:Die Microservice-Architektur vereinfacht die Anwendungsskalierung. Um eine neue Funktion zu implementieren, schreiben Sie einfach einen neuen Dienst. Wenn die Funktion nicht mehr benötigt wird, kann der Microservice deaktiviert werden. Jeder Microservice ist ein separates Projekt, daher ist es einfach, die Arbeit an den Entwicklungsteams zu verteilen.
Lesen Sie mehr über die Skalierungsmechanismen von Microservice-Systemen in dem Buch von Martin L. Abbott, The Art of Scalability.
Nachteile:Es ist schwer, nach Fehlern zu suchen. Im Gegensatz zu monolithischen Systemen (wenn sich alle Funktionen im selben Kernel befinden) kann es schwierig sein, festzustellen, warum die Anforderung "gefallen" ist. Sie müssen zu den Protokollen des "Schuld" -Prozesses gehen, um Einzelheiten zu erfahren (wenn es mehrere gibt, wird das Problem verschlimmert).
Dies schafft zusätzlichen Aufwand für die Übertragung von Nachrichten zwischen Mikrodiensten. Nach unseren Schätzungen kann das Wachstum der Netzwerkkosten 25% erreichen.
Ein weiterer Nachteil ist die
Notwendigkeit, das Konzept der eventuellen Konsistenz (
Kohärenz auf lange Sicht )
in Kauf zu nehmen . Microservices verfügen über eigene Data Warehouses, auf die andere Microservices zugreifen. Informationen über Änderungen an diesen Daten werden nicht sofort über das System verteilt. Daher treten Situationen auf, in denen einige Microservices (wenn auch für einen extrem kurzen Zeitraum) veraltete Daten haben.
Verwendungszweck:- Bei großen Projekten mit hoher Belastung. Beispielsweise werden Microservices von Streaming-Plattformen verwendet. Content Delivery-Systeme und andere Support-Services können unabhängig voneinander skaliert werden, um sich an Laständerungen anzupassen.
- In Systemen, die "gemischte" Ressourcen verwenden. Wenn ein Teil der Anwendung mehr Prozessorzeit und der zweite Speicher benötigt, ist es sinnvoll, sie in Mikrodienste aufzuteilen. Dann können sie auf verschiedenen Computern gehostet werden - mit einer leistungsstarken CPU bzw. einer großen Menge an Speicher.
- Wenn Sicherheit benötigt wird . Da Microservices isoliert sind und über eine API kommunizieren, kann garantiert werden, dass nur die Informationen übertragen werden, die ein bestimmter Service benötigt. Dies ist wichtig, wenn Sie mit Passwörtern oder Zahlungskartendaten arbeiten.
Warum wechseln wir in 1cloud zu Microservices?
Wie bereits erwähnt, basiert die Basis der von uns bereitgestellten Dienste (
Private Cloud ,
virtuelle Server ,
Objektwolkenspeicher usw.) auf einer mehrstufigen Architektur. Sie zeigte sich auf der guten Seite, aber jetzt begann ihre Skalierbarkeit zu schwinden.
Wir werden immer mehr Partner, die ihre Lösungen auf Basis unserer Franchise-Plattform anbieten. Es gibt entfernte Standorte und Dienste, deren Verwaltung von einem einzigen Punkt aus schwierig wird (insbesondere befinden sich unsere Geräte in mehreren Rechenzentren
in Russland, Kasachstan und Weißrussland ).
Um die Skalierung bestehender Funktionen und die Einführung neuer Funktionen zu vereinfachen, übertragen wir unsere gesamte Infrastruktur in
1cloud auf Microservices.

Wir wollen sie in separate Module aufteilen und statt einer komplexen Datenbank N einfache erhalten. In der neuen Architektur verfügt daher jedes Feature über eine separate Datenbank. Es ist viel bequemer und effizienter in der Unterstützung und Entwicklung.
Wir werden in der Lage sein, die Arbeit an Diensten auf mehrere Entwickler aufzuteilen (Spezialisierungen im Unternehmen hervorheben) und effektiv horizontal zu skalieren - bei Bedarf verbinden wir einfach neue Mikrodienste.
Unsere Kunden erhalten auch eine Reihe von Vorteilen. Da Microservices nicht miteinander verbunden sind und ein bestimmter Dienst ausfällt, ist nur dieser nicht verfügbar. Der Rest funktioniert weiterhin normal. Darüber hinaus funktioniert das Control Panel auch dann weiter, wenn unser Service weltweit abfällt.
Kunden aus Kasachstan und Weißrussland (und anderen Ländern, in denen wir Repräsentanzen eröffnen werden) werden eine deutliche Steigerung der Geschwindigkeit und Reaktionsfähigkeit der Schnittstellen feststellen, da sich die Bedienfelder vor Ort befinden werden.
Was wurde bereits getan?
Bisher haben wir nur den ersten Piloten implementiert: „Monitoring Service“. Die restlichen Dienste werden Ende 2018 - Anfang 2019 - auf eine neue Strecke übertragen.
Gleichzeitig legt die neue Architektur die technologische Grundlage für die nächste Stufe - die Migration zu Containern. Jetzt verwenden wir die Windows-Infrastruktur und um zu Containern zu wechseln, müssen wir den gesamten gesammelten Code in .NetCore umschreiben und auf Linux übertragen.
Wir planen, Anfang 2019 einen neuen Übergang zu beginnen und ihn Ende nächsten Jahres abzuschließen.
In einfachen Worten darüber, woran man sich bei Architektur erinnern sollte- Mehrstufige Architektur - Die Anwendung ist in Ebenen unterteilt, von denen jede einen genau definierten Satz von Funktionen ausführt. Jede Ebene kann einzeln geändert werden. Zu den Mängeln zählen die geringe Geschwindigkeit des Codes und die Schwierigkeit, Fehler zu finden.
Geeignet für die Entwicklung von Anwendungen, die schnell auf den Markt gebracht werden müssen. Wird häufig zum Erstellen von Unternehmensdiensten verwendet. - Ereignisorientierte Architektur - hier schreibt der Entwickler die Reaktion des Systems auf Ereignisse vor. Wenn beispielsweise Daten empfangen werden, schreiben Sie diese in eine Datei. Anwendungen, die auf einer ereignisorientierten Architektur basieren, sind einfach zu skalieren, da alle Ereignishandler nichts über die Implementierung des anderen wissen. Das Debuggen solcher Systeme ist jedoch schwierig - eine einzelne Aktion kann mehrere Aktionsketten gleichzeitig verursachen (es ist schwer zu verstehen, welche den Fehler verursacht hat).
Dient zum Erstellen asynchroner Systeme, zum Organisieren grafischer Schnittstellen und von Messagingsystemen. - Mikrokernel-Architektur - besteht aus zwei Schlüsselkomponenten: Plugins und dem Kernel. Plugins sind für die Geschäftslogik verantwortlich, und der Kernel ist für das Laden und Entladen verantwortlich. Diese Aufgabentrennung vereinfacht die Systemunterstützung. Dies kann jedoch die Leistung beeinträchtigen - dies hängt direkt von der Anzahl der angeschlossenen und aktiven Module ab.
Es eignet sich für die Entwicklung erweiterbarer Anwendungen, die von einer großen Anzahl von Personen verwendet werden, sowie für Systeme mit einer Reihe von Regeln, die häufig aktualisiert werden müssen (Plugins garantieren eine einfache Aktualisierung). - Microservice-Architektur - Anwendungen sind in Funktionen unterteilt - Microservices. Jeder Microservice ist eine unabhängige Komponente mit einer eigenen Geschäftslogik. Diese Komponenten kommunizieren über die API miteinander. Solche Anwendungen sind einfach zu entwickeln (es ist möglich, die Arbeit auf Entwicklungsteams zu verteilen), aber es ist schwierig, Fehler zu beheben.
Wird in großen Projekten mit hoher Last verwendet, die eine erhöhte Sicherheit erfordern.
Was schreiben wir noch auf 1cloud Blog: