Hallo Habr!
Die heutige Übersetzung berührt nicht nur und nicht so sehr Microservices - ein Thema, das heute jeder auf den Lippen hat -, sondern erinnert auch daran, wie wichtig es ist, einen Spaten einen Spaten zu nennen. Der Übergang zur Microservice-Architektur ist manchmal notwendig, erfordert jedoch, wie der Autor noch einmal betont, eine sorgfältige Abwägung der Folgen. Viel Spaß und fruchtbares Lesen!

Von Zeit zu Zeit stelle ich die gleiche Frage.
Gibt es eine so wichtige Wahrheit, dass nur wenige mit Ihnen übereinstimmen? - Peter Thiel
Bevor ich mich für diesen Beitrag hinsetzte, habe ich mich lange mit diesem Thema zu einem Thema beschäftigt, das heute einen ernsthaften Trend aufweist - es geht um Microservices. Ich denke jetzt habe ich etwas zu erzählen; Einige Ergebnisse basieren auf Reflexion, andere auf praktischen Erfahrungen. Also, ich sage es dir.
Beginnen wir mit einer wichtigen Wahrheit, die uns auf dem Weg wie ein Polarstern als Bezugspunkt dienen wird.
Die meisten Microservice-Implementierungen sind nichts anderes als verteilte Monolithen.
Ära der Monolithen
Jedes System begann als monolithische Anwendung. Ich werde hier nicht auf Details dieses Themas eingehen - viele haben bereits über viele geschrieben. Der Löwenanteil der Informationen über Monolithen ist jedoch Themen wie Entwicklerproduktivität und Skalierbarkeit gewidmet, während das wertvollste Kapital eines Internetunternehmens in den Klammern bleibt: Daten.
Typische monolithische AnwendungsarchitekturWenn Daten so wichtig sind, warum wird dann allen anderen Themen alle Aufmerksamkeit geschenkt, aber nicht ihnen? Die Antwort ist im Allgemeinen einfach: Weil sie nicht so schmerzhaft sind wie die Datenfrage.
Vielleicht ist der Monolith die einzige Phase im Lebenszyklus des Systems, in der Sie:
- Verstehen Sie Ihr Datenmodell vollständig.
- Sie können mit Daten zusammenarbeiten (es wird davon ausgegangen, dass Ihre Datenbank für Ihre Anwendung korrekt ausgewählt ist).
In Bezug auf die Daten ist der Monolith ideal. Und da Daten das wertvollste Kapital eines Unternehmens sind, ist es besser, den Monolithen nicht zu zerbrechen, es sei denn, Sie haben einen sehr guten Grund oder eine Kombination solcher Gründe. In den meisten Fällen ist der entscheidende Grund für diese Art die Notwendigkeit der Skalierung (da wir in der realen Welt mit ihren inhärenten physischen Einschränkungen leben).
Wenn dieser Moment eintrifft, geht Ihr System höchstwahrscheinlich in eine neue Hypostase über: Es
verwandelt sich in einen verteilten Monolithen .
Die Ära der verteilten Monolithen
Nehmen wir an, in Ihrem Unternehmen läuft es gut und die Anwendung muss wachsen. Sie haben immer mehr große Kunden, und Ihre Anforderungen an die Abrechnung und Berichterstellung haben sich sowohl hinsichtlich einer Reihe von Möglichkeiten als auch hinsichtlich ihres Volumens geändert.
Wenn Sie sich ernsthaft mit dem Abriss des Monolithen befassen, werden Sie versuchen, zwei kleine Dienste zu implementieren, von denen einer die Berichterstattung und der zweite die Abrechnung ermöglicht. Diese neuen Dienste werden höchstwahrscheinlich eine HTTP-API bereitstellen und über eine dedizierte Datenbank für die langfristige Speicherung des Status verfügen. Nach vielen Commits erhalten Sie, wie wir bei
Unbabel , möglicherweise etwas, das der folgenden Abbildung ähnelt.
Eine allgemeine Ansicht der Systemarchitektur nach dem Trennen von Abrechnungs- und Berichterstellungsdiensten von der monolithischen HauptanwendungAlles läuft nach Plan.
- Das Team teilt den Monolithen weiterhin in kleinere Systeme auf.
- Kontinuierliche Integrations- / Lieferförderer arbeiten wie am Schnürchen.
- Kubernetes Cluster ist gesund, Ingenieure sind produktiv und mit allem zufrieden.
Das Leben ist schön.
Aber was ist, wenn ich sage, dass gerade abscheuliche Verschwörungen gegen Sie weben?
Wenn Sie sich nun Ihr System ansehen, werden Sie feststellen, dass die Daten auf viele verschiedene Systeme verteilt wurden. Sie haben mit der Phase begonnen, in der Sie eine eindeutige Datenbank hatten, in der alle Datenobjekte gespeichert waren, und jetzt haben sich Ihre Datenobjekte an verschiedenen Orten ausgebreitet. Vielleicht denken Sie, dass es kein Problem gibt, da Microservices erforderlich sind, um Abstraktionen zu erstellen und Daten zu versiegeln, wodurch die interne Komplexität des Systems verborgen bleibt.
Du hast absolut recht. Mit zunehmender Größe treten jedoch komplexere Probleme auf: Jetzt müssen Sie zu jedem Zeitpunkt die Geschäftsanforderungen erfüllen (z. B. um eine Metrik zu verfolgen) und müssen auf Daten zugreifen, die sich in mehr als einem System befinden.
Was tun? In der Tat gibt es viele Möglichkeiten. Aber in Eile müssen Sie auch eine große Anzahl von Kunden bedienen, die sich kürzlich bei Ihnen registriert haben, damit Sie ein Gleichgewicht zwischen „schnell“ und „gut“ finden können. Nachdem Sie die Details besprochen haben, beschließen Sie, ein zusätzliches System zu erstellen, das eine bestimmte ETL-Arbeit ausführt und zur Lösung der endgültigen Aufgaben beiträgt. Dieses System muss Zugriff auf alle gelesenen Replikate haben, die die benötigten Informationen enthalten. Die folgende Abbildung zeigt, wie ein solches System funktionieren könnte.
Ein verallgemeinertes Beispiel für ein analytisches ETL-System (in Unbabel haben wir es Automatic Translation Analytics genannt)Bei Unbabel haben wir diesen Ansatz verwendet, da:
- Die Leistung jedes Mikrodienstes wird dadurch nicht zu stark beeinträchtigt.
- Es sind keine größeren Infrastrukturänderungen erforderlich (fügen Sie einfach einen neuen Microservice hinzu).
- Wir konnten unsere Geschäftsanforderungen schnell genug erfüllen.
Die Erfahrung zeigt, dass dieser Ansatz für einige Zeit funktionieren wird - bis ein bestimmtes Ausmaß erreicht ist. Bei Unbabel hat er uns bis vor kurzem sehr gute Dienste geleistet, als wir uns immer ernsteren Herausforderungen stellten. Hier sind einige Dinge, die uns Kopfschmerzen bereiteten:
1. DatenänderungenEiner der Hauptvorteile von Microservices ist die Einkapselung. Die interne Darstellung der Daten kann sich ändern, hat jedoch keine Auswirkungen auf die Clients des Systems, da diese über eine externe API kommunizieren. Unsere Strategie erforderte jedoch einen direkten Zugriff auf die interne Darstellung der Daten. Sobald das Team nur einige Änderungen an der Darstellung der Daten vorgenommen hat (z. B. ein Feld umbenennen oder den Typ von
text
in UUID ändern), mussten wir auch unsere ETL- ändern und erneut bereitstellen. Service.
2. Die Notwendigkeit, viele verschiedene Datenschemata zu verarbeitenDa die Anzahl der Systeme, mit denen wir uns verbinden mussten, zunahm, mussten wir uns mit immer heterogeneren Darstellungsweisen für Daten befassen. Es war offensichtlich, dass wir nicht alle diese Schemata, die Beziehungen zwischen ihnen und ihren Darstellungen skalieren konnten.
Die Wurzel allen ÜbelsUm ein vollständiges Bild davon zu bekommen, was im System passiert, mussten wir bei einem Ansatz anhalten, der einem Monolithen ähnelt. Der ganze Unterschied bestand darin, dass wir nicht ein System und eine Datenbank hatten, sondern Dutzende solcher Paare, jedes mit seiner eigenen Datendarstellung; Darüber hinaus wurden in einigen Fällen dieselben Daten auf mehreren Systemen repliziert.
Ich nenne ein solches System lieber einen verteilten Monolithen. Warum? Da es für die Verfolgung von Änderungen im System völlig ungeeignet ist, besteht die einzige Möglichkeit, den Status des Systems anzuzeigen, darin, einen Dienst zu erfassen, der eine direkte Verbindung zu den Data Warehouses aller Microservices herstellt. Es ist interessant zu sehen, wie viele Kolosse des Internets zu einem bestimmten Zeitpunkt ihrer Entwicklung ebenfalls vor ähnlichen Herausforderungen standen. Ein gutes Beispiel in diesem Fall, das ich immer gerne gebe, ist das LinkedIn-Netzwerk.
Dies ist die Art von Datenunglück, das die Informationsflüsse von Linkedin um 2011 herum darstellten - QuelleIm Moment wundern Sie sich vielleicht: "Was werdet ihr mit all dem machen?" Die Antwort ist einfach: Sie müssen Änderungen verfolgen und wichtige Aktionen verfolgen, sobald sie stattfinden.
Brechen Sie einen verteilten Monolithen mithilfe von Event SourcingWie praktisch der Rest der Welt reagieren Systeme im Internet. Eine Anforderung an die API kann daher zum Einfügen eines neuen Datensatzes in die Datenbank führen. Derzeit stören uns solche Details in den meisten Fällen nicht, da wir hauptsächlich daran interessiert sind, den Status der Datenbank zu aktualisieren. Das Aktualisieren des Status einer Datenbank ist eine bedingte Folge eines Ereignisses (in diesem Fall einer API-Anforderung). Das Ereignisphänomen ist einfach und dennoch ist das Potenzial von Ereignissen sehr groß - sie können sogar zur Zerstörung eines verteilten Monolithen verwendet werden.
Ein Ereignis ist nichts anderes als eine unveränderliche Tatsache einer Änderung, die in Ihrem System aufgetreten ist . In der Microservice-Architektur werden Ereignisse kritisch und helfen, Datenströme zu verstehen und auf ihrer Grundlage den Gesamtzustand mehrerer Systeme abzuleiten. Jeder Mikrodienst, der eine Aktion ausführt, die aus Sicht des gesamten Systems interessant ist, sollte ein Ereignis zusammen mit allen wesentlichen Informationen generieren, die sich auf die Tatsache beziehen, dass dieses Ereignis darstellt.
Vielleicht haben Sie eine Frage:
"Wie können Microservices, die Ereignisse erzeugen, mir helfen, das Problem des verteilten Monolithen zu lösen?"
Wenn Sie Systeme haben, die Ereignisse generieren, gibt es möglicherweise ein Faktenprotokoll mit den folgenden Eigenschaften:
- Keine Bindung an ein Data Warehouse: Ereignisse werden normalerweise in Binärformaten wie JSON, Avro oder Protobufs serialisiert.
- Unveränderlichkeit: Sobald ein Ereignis generiert wird, kann es nicht mehr geändert werden.
- Reproduzierbarkeit: Der Zustand des Systems zu einem bestimmten Zeitpunkt kann wiederhergestellt werden. Dazu reicht es aus, das Ereignisprotokoll erneut abzuspielen.
Mit diesem Protokoll können Sie den Status mithilfe einer beliebigen Logik auf Anwendungsebene anzeigen. Sie sind nicht mehr mit einer Reihe von Mikrodiensten und
N Arten der Darstellung der Daten verknüpft. Die einzige Quelle der Wahrheit und Ihr einziges Data Warehouse ist jetzt das Repository, in dem Ihre Ereignisse gespeichert sind.
Hier sind einige Gründe, warum das Ereignisprotokoll für mich der Weg zu sein scheint, um den verteilten Monolithen zu zerstören:
1. Die eine Quelle der WahrheitAnstatt N Datenquellen zu verwalten, die möglicherweise für die Verbindung mit (mehreren) heterogenen Datenbanken erforderlich sind, wird in diesem neuen Szenario die endgültige Wahrheit in genau einem Repository gespeichert: dem Ereignisprotokoll.
2. Universelles DatenformatIn der vorherigen Version des Systems mussten wir uns mit vielen Datenformaten befassen, da wir direkt mit der Datenbank verbunden waren. Im neuen Layout können wir viel flexibler handeln.
Angenommen, Ihnen hat ein Instagram-Foto gefallen, das von einem Ihrer Freunde gepostet wurde. Eine solche Aktion kann beschrieben werden: "
Benutzer X mochte Bild P ". Und hier ist eine Veranstaltung, die diese Tatsache darstellt:
Ein Ereignis, das dem AVO-Ansatz (Actor, Verb, Object) entspricht und die Tatsache simuliert, dass der Benutzer das gewünschte Bild auswählt.3. Schwächung der Kommunikation zwischen Produzenten und KonsumentenNicht zuletzt ist einer der größten Vorteile des Veranstaltungsbetriebs die effektive Schwächung der Kommunikation zwischen Datenproduzenten und -konsumenten. Diese Situation vereinfacht nicht nur die Skalierung, sondern verringert auch die Anzahl der Abhängigkeiten zwischen ihnen. Der einzige Vertrag, der in diesem Fall zwischen den Systemen verbleibt, ist das Ereignisdiagramm.
Zu Beginn dieses Artikels wurde die Frage gestellt: Gibt es eine so wichtige Wahrheit, in der nur wenige mit Ihnen übereinstimmen?
Lassen Sie mich zum Abschluss dieser Exkursion darauf zurückkommen. Ich glaube, dass die meisten Unternehmen Daten nicht als „erstklassige Entitäten“ betrachten, wenn sie mit der Migration zur Microservice-Architektur beginnen. Es wird argumentiert, dass alle Datenänderungen weiterhin über die API vorgenommen werden können, aber dieser Ansatz führt letztendlich zu einer ständigen Komplikation des Dienstes selbst.
Ich glaube, dass der einzig wahre Ansatz zur Erfassung von Datenänderungen in einer Microservice-Architektur darin besteht, Systeme dazu zu bringen, Ereignisse gemäß einem streng definierten Vertrag zu emittieren. Mit einem korrekt kompilierten Ereignisprotokoll können Sie viele Daten basierend auf beliebigen Geschäftsanforderungen anzeigen. In diesem Fall müssen Sie nur unterschiedliche Regeln auf dieselben Fakten anwenden. In einigen Fällen kann eine solche Datenfragmentierung vermieden werden, wenn Ihr Unternehmen (insbesondere Ihre Produktmanager) die Daten als Produkt behandelt. Dies ist jedoch ein Thema für einen anderen Artikel.