Keine Angst vor Microservice: Alexey Baitov über den Einsatz von Microservice-Architektur in der Praxis

Für einige ist Microservices die Fähigkeit, eine Anwendung in einem relativ modernen Stil zu wiederholen und umzugestalten. Diese architektonische Lösung ist aufgrund der Besonderheiten des Zusammenspiels verschiedener Teile der Anwendung nicht für andere geeignet. In jedem Fall ist es bei der Auswahl einer Architektur hilfreich, die Erfahrungen anderer vom Übergang von einem Monolithen zu einer Reihe von Diensten zu untersuchen.

Wir haben darum gebeten, unsere Fallstudie über die Entwicklung und Bereitstellung von Mikrodiensten zu teilen. Alexei Baitov, leitender Ingenieur von 2GIS. Lassen Sie uns über Architekturlösungen, Bereitstellung und Skalierbarkeit sprechen. Fragen wir nach Trends und nur nach praktischen Werkzeugen.



- Alexey, bitte erzähl uns ein wenig über dich und dein Team in 2GIS . Woran arbeiten Sie gerade?

Ich bin 2003 als Systemadministrator zur IT gekommen und habe mich 2011 in die Entwicklung gestürzt. Während dieser Zeit arbeitete er in PHP, JavaScript, implementierte eine Reihe von RESTful-Diensten und einen Python-Treiber für Git. Ich arbeite seit 2015 in 2GIS.

Er war an der Entwicklung von zwei Microservice-Architekturen beteiligt. Der erste bestand aus einem Dienst. Es war ein asynchroner Reverse-Proxy mit einem Cache. Tatsächlich war er damit beschäftigt, Nachrichten zu senden. Ich war der einzige, der an der Erarbeitung der Anforderungen, der Entwicklung und dem Aufbau von DevOps beteiligt war, aber Experten unserer 2GIS-Firma haben mir geholfen.

Der Dienst wurde in Go geschrieben. Durch die schnelle Kompilierung konnte ich nicht warten und konnte mich auf die kontinuierliche Bereitstellung konzentrieren. Dann haben wir gerade angefangen, GitLab CI , Prometheus , Grafana und Deis (Open-Source-Analogon von Heroku ) zu verwenden. Wir haben ein Team von Infrastruktur und Betrieb, das zum Zeitpunkt meiner Entwicklung all diese Infrastrukturlösungen auf das produktionsbereite Niveau gebracht hat. Ich habe mich dazu entschlossen und einen unabhängigen Microservice erfolgreich implementiert.

Vor zwei Jahren wechselte ich bei einem neuen Projekt zu einem anderen Team, wo ich mich in Scala mit funktionaler Programmierung beschäftigte. Unser Team hat von Grund auf eine Microservice-Architektur für die Speicherung von 2GIS-Werbematerialien in Scala, C # und JavaScript entwickelt. Ich habe den Grundstein für alle Services mit den Tools und Erfahrungen gelegt, die für den Aufbau von DevOps-Praktiken (kontinuierliche Bereitstellung und Wartung) gesammelt wurden. Die Architektur hat sich vom Prototyp zum Industriebetrieb entwickelt. Sie hat zwei Monolithen aufgenommen, besteht nun aus 15 Diensten und wird ständig erweitert.

- Stimmen Sie zu, dass Microservices im Wesentlichen eine Reihe von unabhängig bereitgestellten Diensten sind, die gemeinsame Merkmale aufweisen, dh eine Reihe bestimmter Funktionen verleiht ihnen das Erscheinungsbild eines Microservices? Muss diese Definition erweitert werden? Oder haben Unternehmen tatsächlich ein anderes Verständnis der Microservice-Architektur?

Ich mag die folgende Definition . Die Microservice-Architektur ist ein Architekturstil, der eine Anwendung als eine Sammlung lose gekoppelter Services strukturiert, die eine bestimmte Geschäftslogik implementieren. Services in einer Microservice-Architektur weisen möglicherweise keine gemeinsamen Merkmale auf, werden jedoch in einer gemeinsamen Geschäftslogik kombiniert.
Natürlich wird jedes Unternehmen seinen eigenen Microservice haben. Dies ist eine Reihe von Vorgehensweisen: verteilte Architektur, kontinuierliche Integration und Bereitstellung usw. Wenn Sie das Konzept der Praxis auf die verwendeten Tools erweitern, sind die Optionen für die Implementierung von Microservices sehr unterschiedlich.
- Es gibt unterschiedliche Meinungen über die Zusammensetzung des Teams, die in das Schreiben und Unterstützen von Microservices einbezogen werden sollten. Was denkst du darüber? Was ist die optimale Teamgröße und wie sollte sie durch die Interaktion bei der Entwicklung einer Microservice-Architektur aufgebaut werden? Gibt es ein gutes Beispiel für Teamarbeit aus Ihrer Praxis?

Es wird als richtig angesehen, einen Dienst so zu entwickeln, dass sein gesamter Themenbereich in den Kopf eines Entwicklers passt. Gleichzeitig können mehrere Personen an der Entwicklung dieses Dienstes teilnehmen. Dies hilft, den Busfaktor zu vermeiden, wenn der Entwickler in den Urlaub fuhr oder krank wurde. Durch die korrekte Aufteilung in Dienste kann eine neue Person schnell in den Kontext eintreten.

Die Microservice-Architektur sagt uns, dass sie häufig mehrere Services enthält. Somit kann ein Entwickler nicht tun. Die Microservice-Architektur baut auf dem Produktmodell (oder der allgemeinen Geschäftslogik) auf. Entwickler werden so ausgewählt, dass sich herausstellt, dass sie dieses Modell implementieren und sich gleichzeitig auf den Kunden konzentrieren.

Die Konzentration auf den Kunden wird durch direkten Kontakt zwischen dem Entwickler und dem Kunden organisiert. Entwickler müssen sehen, wie ihr Produkt verwendet wird. Daraus folgen Wünsche nach Wissen auf technologischem Gebiet, die Fähigkeit, das Produkt an den Kunden zu liefern und das Produkt so schnell wie möglich zu begleiten.

Über die Größe des Teams ist es schwer zu sagen. Jeder kennt wahrscheinlich bereits die Aussage von Jeff Bezos, dem Gründer von Amazon, dass die Größe des Teams in der serviceorientierten Entwicklung klein genug sein sollte, damit jeder zwei Pizzen füttern kann. In den Kommentaren zu Habré gab es eine Diskussion zu diesem Thema und sie schrieben, dass eine Person möglicherweise nicht genug eine Pizza hat und daher ein Team aus ein oder zwei Personen bestehen sollte. Martin Fowler zitierte eine Aussage über zwei Pizzen und sagte, es handele sich um große amerikanische Pizzen. Danach gab er an, dass das Team nicht 50, sondern etwa 12 Personen haben sollte. Ich glaube, dass alles vom Produktmodell abhängt. Aber Fowlers Klarstellung über "nicht mehr als 12 Personen" hat in meiner Praxis bisher gewonnen. Mir ist aufgefallen, dass es innerhalb des Teams wünschenswert ist, sich nach technologischen Interessen zu teilen, um Gleichgesinnte zu finden.

Es ist nicht erforderlich, dass jeder im Team alle in der Arbeit verwendeten technologischen Bereiche gut kennt, aber das Gesamtwissen des Teams sollte einheitlich tief sein. Beispielsweise sind zwei Personen am ersten Aufbau einer Bereitstellung beteiligt, und in Zukunft werden sie diese höchstwahrscheinlich auch erheblich verbessern. Gleichzeitig sollte das gesamte Team den Bereitstellungsprozess gut verstehen. Dadurch kann sie ihre Wünsche äußern und Änderungen vornehmen. Warum zwei Leute? Denn manchmal kann eine Person in einen kreativen Stupor geraten. Und in der Diskussion wird die Wahrheit geboren.

Wir haben natürlich auf diesem Prinzip aufgebaut, vereint durch technologische Interessen. In diesem Fall kann der Entwickler auch DevOps-Praktiken festlegen, und der QS-Techniker kann einen zusätzlichen Nichtproduktionsdienst entwickeln (z. B. Erwärmen des Caches oder Suchen nach Anomalien in Daten in verschiedenen Umgebungen).



- Fast jeder Bericht über Microservices beginnt mit der Geschichte, dass „hier wir einen Eisberg hatten und wir sägten, sägten, sägten ... Die neuen Teile der Anwendung wurden auf der Basis von Microservices erstellt, und dann begannen sie, die„ Teile “vom Hauptmotor zu trennen ... ""

Sagen Sie mir, sind Sie ein Befürworter der Entwicklung von Grund auf neu oder kann es Situationen geben, in denen es sich lohnt, aus einem Monolithen eine schrittweise Schlussfolgerung zu ziehen? Wie bestimme ich die Exit-Strategie?

Ich bin ein Befürworter der Entwicklung von Grund auf neu. Dies funktioniert jedoch nur, wenn der Funktionsumfang nicht zu kompliziert ist. Normalerweise wird ein kleiner MVP-Monolith hergestellt. Und manchmal ist es notwendig, die interne Implementierung mehrmals radikal zu ändern. Dies kann sowohl durch eine Änderung der technischen Aufgabe als auch durch die Tatsache verursacht werden, dass ein Verständnis für die Implementierung entsteht - Abstraktionen auf hoher Ebene erscheinen auf der Ebene des Geschäftsmodells. Danach können Sie mit der Microservice-Architektur fortfahren.

Wenn Sie diese Abstraktionen jedoch gleich zu Beginn durcharbeiten und in verschiedenen Notationen (UML, BPMN, IDEF) zeichnen, damit alle Teilnehmer des Prozesses verstehen, womit sie arbeiten, ist es durchaus möglich, sofort eine Microservice-Architektur zu implementieren.

Unser Weg zur Microservice-Architektur war nicht gerade. Zuerst gab es einen Monolithen. Er verarbeitete Werbematerialien in Textform. Vor dreieinhalb Jahren mussten wir mit grafischen Werbematerialien (Bilder, Logos) arbeiten. Es bestand der Wunsch, in die Geschäftslogik einzuführen, was bei der Arbeit mit Textwerbematerialien fehlte.
Um ein neues Geschäftsmodell zu testen, haben wir die Arbeit mit grafischen Werbematerialien als zweitem Monolithen auf einem anderen Technologie-Stack implementiert. Nach anderthalb Betriebsjahren stellten wir fest, dass dieser Ansatz korrekt war.
Während dieser Zeit haben wir eine Menge Wunschliste bekommen, die die Rauheit der Geschäftslogik enthüllte.

Die Implementierung des zweiten Monolithen war schwierig auf den ersten auszudehnen. Aus diesem Grund haben wir beschlossen, die Entwicklung nicht in zwei Monolithen gleichzeitig durchzuführen, sondern sie im Rahmen der dritten Architektur nach dem sehr neuen Geschäftsmodell zu kombinieren. Ein Team von sieben Entwicklern, einem QS-Ingenieur und zwei Analysten wurde erstellt. Zwei Entwickler aus diesem Team haben zuvor den ersten Monolithen erstellt und unterstützt, und einen weiteren - den zweiten Monolithen. Das heißt, unser Team bereits am Eingang kannte die Fallstricke früherer Monolithen gut.

Der erste Monolith wurde in C # geschrieben. Der zweite ist in PHP. Wir wollten die debuggten, umfangreichen Codeteile des ersten Monolithen nicht verlieren, und gleichzeitig waren Multithreading, sicherer Code und starke Typisierung erforderlich. Der PHP-Code fiel teilweise nicht unter diese Anforderungen. Daher blieb C # die Basis und implementierte das, was es im Rahmen des ersten Monolithen gut tat - Arbeiten mit dem Inhalt von Werbematerialien - aber auf der Basis eines anderen Speichers: S3-kompatibler Speicher und Kafka.

Um mit dem sehr neuen Geschäftsmodell zu arbeiten, wurden diesmal Scala und die PostgreSQL-Datenbank ausgewählt. Scala hat unsere technischen Anforderungen erfüllt. Darüber hinaus befanden sich Scala-Entwickler auf derselben Etage wie C # -Entwickler. Dies verkürzte die Zeit für die Teamkommunikation. Das Gesetz von Conway hat funktioniert - die Struktur des Unternehmens bestimmte die Struktur des Antrags. Der PHP-Entwickler hat sich zu einem Scala-Entwickler entwickelt. Ich habe gerade die Arbeit an einem unabhängigen Mikroservice auf Golang mit einem vollständigen CI / CD-Zyklus beendet. Danach bin ich dem Team beigetreten und wurde auch Scala-Entwickler.

Es ist interessant, was genau ich für die Arbeit mit Scala-Geschäftslogik und nicht mit C # vorgeschlagen habe. Tatsache ist, dass wir nicht genügend C # -Entwickler hatten. PHP-shnik und ich wollten für Scala umschulten. Außerdem hatten wir die Gelegenheit, einen erfahrenen Scala-Entwickler zu gewinnen. Ein weiterer Punkt: Wenn wir alles in C # implementieren würden, könnten wir entweder eine Microservice-Architektur oder einen anderen Monolithen am Ausgang erhalten. Die Aufteilung in Scala und C #, unterschiedliche Speicheranforderungen und die Verfügbarkeit erfahrener Entwickler in jedem der erforderlichen Bereiche - all dies wies direkt auf die Microservice-Architektur hin. Davon haben wir nur profitiert. Vor einem Jahr wurde die Microservice-Architektur für die Arbeit mit Grafik- und Textmaterialien kommerziell in Betrieb genommen und ist bis heute erfolgreich in Betrieb.

Auf die Frage, ob es möglich ist, eine Microservice-Architektur von Grund auf neu zu erstellen. Vor anderthalb Jahren, als wir an der Microservice-Architektur arbeiteten, hatten wir die Forderung, eine neue Richtung in unseren Produkten einzuschlagen - Video-Werbematerialien. Es war notwendig, schnell ein neues Verkaufsmodell zu testen. Unsere Architektur steckte noch in den Kinderschuhen. Die Arbeit mit Videomaterial deckte einen neuen Technologiebereich ab. Wir haben beschlossen, den Entwicklungsvektor nicht zu ändern, und MVP für Videomaterial als eigenständige Mikroservice-Architektur in C # und vertrauenswürdigem Video-Hosting implementiert. Dies ist eine erfolgreiche Erfahrung, und wir haben einen Bericht zu diesem Thema. Somit haben wir zwei parallel existierende Microservice-Architekturen. MVP hat nicht viel entwickelt, Wishlist hat sich auch darauf angesammelt, und bald werden wir alles im Rahmen einer einzigen Microservice-Architektur kombinieren - wir werden ein einziges Repository mit Werbetext-, Grafik- und Videomaterial erhalten.

- Es gibt sofort zwei wichtige Faktoren, die für Microservices sprechen. Das erste ist die Fähigkeit, einzelne Teile in die Cloud auszugeben, und infolgedessen eine kolossale Skalierbarkeit. Die zweite ist die Möglichkeit, einen separaten Dienst in einer anderen Sprache zu erstellen. Welche weiteren Vorteile der Umstellung auf Microservices sehen Sie? Nun, von den Minuspunkten möchte ich natürlich auch hören.

Wenn wir über die technologische Komponente sprechen, umfassen die Vorteile zusätzlich zu den oben genannten die Möglichkeit, einen anderen Stapel von Technologien zu verwenden. Und wenn er nicht zu uns passt, werden wir einen anderen wählen. Neue Technologien umgehen die Probleme alter Lösungen. Die Microservice-Architektur bietet auch Stabilität und Unabhängigkeit: Die Verschlechterung eines Dienstes sollte nicht zur vollständigen Verschlechterung des gesamten Systems führen. Die Service-Composability ermöglicht die Wiederverwendung von Service-Funktionen in anderen Microservice-Architekturen. Aus Sicht der Organisationskomponente können Sie durch die Aufteilung in Services die Entwicklung in verteilte Teams oder ein großes Team aufteilen.
Die Hauptnachteile der Microservice-Architektur: Sie ist viel komplizierter und ihre Implementierung ist teurer.
Sie müssen auch darauf vorbereitet sein, Serviceverträge zu unterstützen, das richtige RAS-Protokoll auszuwählen, Probleme der sicheren dienstübergreifenden Interaktion und mögliche Fehler zu beheben sowie verteilte Transaktionen zu deduplizieren und zu verwalten.

Im Allgemeinen finden Sie im öffentlichen Bereich viele Informationen und Materialien zur Arbeit damit. Tatsächlich hängt alles von der Aufgabe ab. In meiner Praxis waren die Pluspunkte immer wichtiger als die Minuspunkte.

Es lohnt sich immer noch, an die Worte von Sam Newman zu erinnern: Je weniger der Service, desto mehr manifestieren sich alle Vor- und Nachteile der Microservice-Architektur.

- Sie haben einige interessante Berichte über Microservices. Bereitstellung von Microservices und der Continuous Deployment-Ansatz in der Microservice-Architektur . Auf einer der Folien der ersten befinden sich Bereitstellungsvorlagen, und im Bericht sagen Sie, dass für Sie der Trendansatz die Verteilung über Container ist. In dieser Zeit hat sich nichts geändert? Ein Haufen Docker + Kubernetes hat seine Relevanz nicht verloren?

Wir übertragen immer mehr Dienste auf dieses Paket. Ich denke, wir haben die richtige Richtung gewählt und planen vorerst, daran festzuhalten. Wenn sich etwas ändert, werde ich Ihnen dies in einem neuen Bericht oder Interview mitteilen.

- Wie reibungslos ist die kontinuierliche Bereitstellung und Übertragung von Microservices auf Produkte?

Es hängt alles davon ab, wie der Prozess aufgebaut wird. Auf den ersten Blick scheint alles einfach zu sein. Dienste sind unabhängig und werden separat bereitgestellt. Eine schwache Kohärenz wird durch unterschiedliche Ansätze bei der Entwicklung des Vertrags sichergestellt. Und hier muss man wählen. Sie können beispielsweise die Versionierung eines Vertrags implementieren oder einen Dienst hinzufügen, um einen Vertrag zu trennen (Vertragsentkopplung).

Wenn in einer Microservice-Architektur in der aktiven Entwicklung 10 oder mehr Dienste gleichzeitig vorhanden sind und jeder seine eigene Versionierung hat, liegt ein Problem der Versionskonsistenz vor. Wir dürfen versuchen, die Kompatibilität von Diensten verschiedener Versionen nicht zu verwechseln.

Kontinuierliche Bereitstellung bedeutet, dass wir die Anwendung jederzeit in jeder Umgebung bereitstellen können.
Eine Anwendung in der Microservice-Architektur ist eine Sammlung von Diensten. Daher müssen wir zu jedem Zeitpunkt eine stabile Kombination von Serviceversionen kennen. Und woanders müssen wir eine Reihe von Domänenadressen und anderen Parametern haben, die für verschiedene Umgebungen spezifisch sind, um Dienste zu konfigurieren und miteinander zu verknüpfen.
All dies muss irgendwo gespeichert werden, um Änderungen an mehreren Stellen zu korrigieren (Microservices sind schließlich unabhängig) und um nicht verwirrt zu werden.

Kontinuierliche Bereitstellung bedeutet, dass jederzeit ein Rollback auf eine beliebige Version möglich ist. Dementsprechend kann es sein, dass Sie mehrere Dienste gleichzeitig zurücksetzen müssen und die korrekte umgekehrte Reihenfolge der Dienstbereitstellung beachten müssen.

In einem meiner Berichte spreche ich über unseren Ansatz zur Entwicklung von Verträgen, wie sie das Problem der Konsistenz von Versionen gelöst haben und wie sie den Bereitstellungsprozess in der Mikrodienstarchitektur von mehr als zehn Diensten aufgebaut haben. Eine kontinuierliche Bereitstellung ist möglicherweise nicht problemlos, aber alles ist lösbar.

- Was könnten die ersten Tools für einen kontinuierlichen Einsatz von Microservices sein? Welche Optionen würden Sie für die Arbeit mit Microservices empfehlen?

Die kontinuierliche Bereitstellung ist eine Folge von Pipelines, einschließlich kontinuierlicher Integration, Integrationstests und Servicebereitstellung für die Orchestrierungsumgebung. Die beliebtesten Step-Sequencing-Tools sind Jenkins 2 Pipelines , TeamCity Build Chains , Bitbucket Pipelines und GitLab CI Pipelines . Zuerst müssen Sie die kontinuierliche Integration (CI) automatisieren. Wir benötigen einen Remote-CI-Server, um Tests für diese Assembly zu erstellen und auszuführen.

Die aufgeführten Tools bieten ihre Lösungen. Wir verwenden GitLab CI und GitLab Runners fungieren als solche Server. Das Build-Artefakt ist das Docker- Image. Im Rahmen der Integrationstests können Sie mit Gatling Last- und kapazitive Tests durchführen, um insbesondere die Ressourcen zu ermitteln, die für die Funktion in einer Orchestrierungsumgebung (z. B. Kubernetes ) erforderlich sind (Prozessor und Speicher). Helm wird häufig für die Bereitstellung verwendet. Mit ihm können Sie die Microservice-Architektur für verschiedene Umgebungen beschreiben. In unserer Firma verwenden wir keinen Helm. Wir haben unser eigenes Bereitstellungstool, das erstellt wurde, als Helm in der Classic-Version war und keine unterschiedlichen Umgebungen unterstützte. Beide Tools haben ähnliche nützliche Eigenschaften, aber die Implementierung und Verteilung sind unterschiedlich. Mit unserem eigenen Tool können wir Verbesserungen vornehmen und alles an unsere Infrastruktur anpassen.

- Welche Technologien sind für kleine und mittlere Unternehmen, die Microservices implementieren möchten, optimal? Ist das ein zu teures Vergnügen für sie?

Zunehmend stoße ich auf Bestätigungen, dass kleine und mittlere Unternehmen nicht in der Lage sind, ihre eigene Orchestrierungsumgebung zu erstellen (z. B. Kubernetes , Docker Swarm oder Apache Mesos ). . ( Google Cloud Platform , Amazon Web Services , Microsoft Azure Oracle Cloud ) .

GitLab GitLab CI. . GitLab Helm . Helm . Helm , , , .

, , , open source, .

Spinnaker Heroku — , , .

— , , , . . ?

, . , , .

( ) . .

. . , (package). .

( ) Docker-, Git. , . , . , .

, . : API. . : . , API. , API , — . , API, .

. , ; API, ; , , .

, , . , ?

— - . , API, , . . .

, , . , , . , , .

— , . 2. , ? ?

. . Mesosphere , OpenShift PaaS IaaS . Deis , Deis . open source Heroku , Heroku Buildpack', Dockerfile' Docker-. . make Deis. .

Deis2 . Deis, Kubernetes. Infrastructure & Operations , , Kubernetes Deis2. , , Deis2, , — Kubernetes. . Deis2 : , pod pod' namespace. Infrastructure & Operations. Kubernetes . Deis2 Kubernetes. Deis2 Kubernetes.

— , , , ? ?

Helm. , . Helm .
Helm , — : , .
Helm chart' chart, , .

2 , 10 . ( backing : Postgres, Kafka, Zookeeper, Ceph). - , yaml- , IDE, . , . Python, Python . , . , . , . , , . . , , , ( ) . , , Helm, Kubernetes - , yaml.

API API Gateway . , — .

, : . , , .
DevOps , . DevOpsConf Russia .

DevOpsConf Russia 1 2 RootConf, , , , . DevOps , .

DevOps , , – . 15 .

Source: https://habr.com/ru/post/de418941/


All Articles