{"id":35906,"date":"2019-10-31T22:07:29","date_gmt":"2019-10-31T19:07:29","guid":{"rendered":"https:\/\/prohoster.info\/blog\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\/"},"modified":"2019-10-31T22:07:29","modified_gmt":"2019-10-31T19:07:29","slug":"perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","title":{"rendered":"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>In diesem Artikel erz\u00e4hle ich, wie das Projekt, an dem ich arbeite, sich von einem gro\u00dfen Monolithen in eine Sammlung von Mikrodiensten verwandelt hat.<\/p>\n<p>Das Projekt hat seine Geschichte bereits Anfang der 2000er Jahre begonnen. Die ersten Versionen wurden in Visual Basic 6 geschrieben. Im Laufe der Zeit wurde klar, dass die Entwicklung in dieser Sprache in der Zukunft schwierig zu unterst\u00fctzen sein w\u00fcrde, da sich sowohl die IDE als auch die Sprache nur wenig weiterentwickelten. Ende der 2000er Jahre wurde beschlossen, auf das vielversprechendere C# umzusteigen. Die neue Version wurde parallel zur \u00dcberarbeitung der alten geschrieben, wobei immer mehr Code in .NET verfasst wurde. Das Backend in C# war zun\u00e4chst auf eine serviceorientierte Architektur ausgelegt, jedoch wurden gemeinsam genutzte Bibliotheken mit Logik verwendet und die Dienste wurden in einem einzigen Prozess ausgef\u00fchrt. Es entstand eine Anwendung, die wir \u201edienstorientierten Monolithen\u201c nannten. <\/p>\n<p>Einer der wenigen Vorteile dieser Kombination war die M\u00f6glichkeit, dass sich die Dienste \u00fcber eine externe API gegenseitig aufrufen konnten. Es gab klare Anzeichen f\u00fcr den \u00dcbergang zu einer korrekteren serviceorientierten Architektur und in Zukunft sogar zu einer Mikrodienste-Architektur. <\/p>\n<p>Unsere Arbeit an der Dekomposition begann etwa im Jahr 2015. Wir haben zwar noch nicht den idealen Zustand erreicht \u2013 einige Teile des gro\u00dfen Projekts lassen sich kaum noch als Monolithen bezeichnen, aber sie sind auch keine Mikrodienste. Dennoch ist der Fortschritt erheblich. <br \/>\nDar\u00fcber werde ich im Artikel berichten.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/132bb4ea6b9dbcdd202ee090f2b86289.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>Inhalt<\/h3>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#1\"> Architektur und Probleme der bestehenden L\u00f6sung<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#2\">Erwartungen an Mikrodienste<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#3\">Probleme beim \u00dcbergang<\/a><\/noindex><\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"#4\">Wie man von einem Monolithen zu Mikrodiensten wechselt<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#5\">Erste Methode<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#6\">Die zweite Methode<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#7\">Dritte Methode<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#8\">Vierte Methode<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#9\">Arbeiten mit der DB<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#10\">Abtrennung bestehender Tabellen<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#11\">Abtrennung mit \u00dcberarbeitung<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#12\">Arbeiten mit Quellcode<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#13\">Infrastrukturprobleme<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#16\">Manuelle Installation in Umgebungen<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#14\">Getrennte Protokollierung<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#15\">Testen und Debuggen von verbundenen Diensten<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><noindex><a rel=\"nofollow\" name=\"1\"><\/a><\/noindex><b><\/p>\n<h3>Architektur und Probleme der bestehenden L\u00f6sung<\/h3>\n<p><\/b><br \/>\nUrspr\u00fcnglich sah die Architektur so aus: UI \u2013 eine separate Anwendung, der monolithische Teil wurde in Visual Basic 6 geschrieben, die Anwendung in .NET war eine Sammlung von verbundenen Diensten, die mit einer recht gro\u00dfen Datenbank arbeiteten.<\/p>\n<p><b>Nachteile der vorherigen L\u00f6sung<\/b><\/p>\n<p><u>Single Point of Failure<\/u><br \/>\nWir hatten einen Single Point of Failure: Die .NET-Anwendung lief in einem Prozess. Wenn in einem der Module ein Fehler auftrat, fiel die gesamte Anwendung aus und musste neu gestartet werden. Da bei uns viele Prozesse f\u00fcr verschiedene Benutzer automatisiert werden, konnten aufgrund eines Fehlers in einem dieser Prozesse einige Zeit lang alle nicht arbeiten. Und bei einem Programmfehler half auch die Redundanz nicht. <\/p>\n<p><u>Warteschlange f\u00fcr Anpassungen<\/u><br \/>\nDieses Problem ist eher organisatorischer Natur. In unserer Anwendung gibt es viele Auftraggeber, die alle die Anpassungen so schnell wie m\u00f6glich durchf\u00fchren m\u00f6chten. Fr\u00fcher war es unm\u00f6glich, dies parallel zu tun, und alle Auftraggeber mussten sich anstellen. Dieser Prozess f\u00fchrte zu Unmut im Gesch\u00e4ft, da sie beweisen mussten, dass ihre Anforderungen Wert hatten. Das Entwicklungsteam verbrachte Zeit damit, diese Warteschlange zu organisieren. Das nahm viel Zeit und Energie in Anspruch, und das Produkt konnte letztendlich nicht so schnell ge\u00e4ndert werden, wie es gew\u00fcnscht war.<\/p>\n<p><u>Suboptimale Ressourcennutzung<\/u><br \/>\nBei der Bereitstellung von Dienstleistungen in einem einheitlichen Prozess haben wir die Konfiguration immer vollst\u00e4ndig von Server zu Server kopiert. Wir wollten die am st\u00e4rksten ausgelasteten Dienste separat betreiben, um Ressourcen nicht zu verschwenden und ein flexibleres Management unseres Bereitstellungsschemas zu erm\u00f6glichen.<\/p>\n<p><u>Moderne Technologien in die Praxis umzusetzen, ist schwierig.<\/u><br \/>\nEin bekanntes Problem f\u00fcr alle Entwickler: Es besteht der Wunsch, moderne Technologien in ein Projekt einzuf\u00fchren, aber es fehlt die M\u00f6glichkeit. Bei einer gro\u00dfen monolithischen L\u00f6sung verwandelt sich jedes Update der bestehenden Bibliothek, ganz zu schweigen von einem Wechsel zu einer neuen, in eine durchaus anspruchsvolle Aufgabe. Man muss lange argumentieren, um dem Teamleiter zu beweisen, dass dies mehr Vorteile bringt, als Nerven kostet. <\/p>\n<p><u>Die Schwierigkeiten bei der Umsetzung von \u00c4nderungen.<\/u><br \/>\nDas war das gr\u00f6\u00dfte Problem \u2013 wir ver\u00f6ffentlichten alle zwei Monate neue Versionen. <br \/>\nJede Ver\u00f6ffentlichung wurde trotz Tests und der Anstrengungen der Entwickler zu einer echten Katastrophe f\u00fcr die Bank. Das Unternehmen war sich bewusst, dass zu Beginn der Woche ein Teil der Funktionalit\u00e4t nicht verf\u00fcgbar sein w\u00fcrde. Und die Entwickler wussten, dass sie eine Woche ernsthafter Vorf\u00e4lle erwarten w\u00fcrden. <br \/>\nDer Wunsch nach Ver\u00e4nderung war bei allen vorhanden. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"2\"><\/a><\/noindex><b><\/p>\n<h3>Erwartungen an Mikrodienste<\/h3>\n<p><\/b><br \/>\n<u>Bereitstellung von Komponenten gem\u00e4\u00df ihrer Verf\u00fcgbarkeit. <\/u>Bereitstellung von Komponenten nach Verf\u00fcgbarkeit durch Decomposition der L\u00f6sungen und Trennung verschiedener Prozesse.<\/p>\n<p><u>Kleine Produktteams.<\/u> Das ist wichtig, da es schwierig war, mit einem gro\u00dfen Team, das an einem alten Monolithen arbeitet, zu managen. Ein solches Team musste nach einem strengen Prozess arbeiten, w\u00e4hrend mehr Kreativit\u00e4t und Unabh\u00e4ngigkeit gew\u00fcnscht war. Dies konnten sich nur kleine Teams leisten.<\/p>\n<p><u>Isolation der Dienste in separaten Prozessen.<\/u> Idealerweise w\u00e4re es w\u00fcnschenswert, sie in Containern zu isolieren, allerdings laufen viele Dienste, die auf dem .NET Framework basieren, nur unter Windows. Es kommen nun Dienste auf .NET Core auf, aber davon gibt es bisher nur wenige.<\/p>\n<p><u>Flexibilit\u00e4t bei der Bereitstellung.<\/u> Wir m\u00f6chten Dienste so kombinieren, wie es f\u00fcr uns notwendig ist, und nicht so, wie es der Code vorschreibt.<\/p>\n<p><u>Nutzung neuer Technologien.<\/u> Das ist f\u00fcr jeden Programmierer interessant.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"3\"><\/a><\/noindex><b><\/p>\n<h3>Probleme beim \u00dcbergang<\/h3>\n<p><\/b><br \/>\nNat\u00fcrlich, wenn es einfach w\u00e4re, den Monolithen in Mikrodienste zu zerlegen, m\u00fcsste man nicht auf Konferenzen dar\u00fcber sprechen und Artikel schreiben. In diesem Prozess gibt es viele Stolpersteine, von denen ich die wichtigsten beschreiben werde, die uns gehindert haben.<\/p>\n<p><b>Das erste Problem<\/b> typisch f\u00fcr die meisten Monolithen: die Koh\u00e4renz der Gesch\u00e4ftslogik. Wenn wir einen Monolithen schreiben, m\u00f6chten wir unsere Klassen wiederverwenden, um keinen \u00fcberfl\u00fcssigen Code zu schreiben. Bei der Umstellung auf Microservices wird dies jedoch problematisch: Der gesamte Code ist relativ eng miteinander verbunden, und es ist schwierig, die Services zu trennen.<\/p>\n<p>Zum Zeitpunkt des Projektstarts gab es im Repository mehr als 500 Projekte und \u00fcber 700.000 Zeilen Code. Das ist ein recht umfangreiches Vorhaben und <b>das zweite Problem<\/b>. Einfach zu versuchen, es in Microservices zu teilen, war nicht m\u00f6glich.<\/p>\n<p><b>Das dritte Problem<\/b> \u2014 fehlende notwendige Infrastruktur. Tats\u00e4chlich haben wir den Quellcode manuell auf die Server kopiert.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"4\"><\/a><\/noindex><b><\/p>\n<h3>Wie man von einem Monolithen zu Mikrodiensten wechselt<\/h3>\n<p><\/b><br \/>\n<u>Abtrennung von Microservices<\/u><\/p>\n<p>Zun\u00e4chst haben wir f\u00fcr uns selbst festgelegt, dass die Abtrennung von Microservices ein iterativer Prozess ist. Von uns wurde immer gefordert, parallel an der Entwicklung der Gesch\u00e4ftsanforderungen zu arbeiten. Wie wir dies technisch umsetzen, ist bereits unser Problem. Daher haben wir uns auf einen iterativen Prozess vorbereitet. Andernfalls funktioniert es nicht, wenn man eine gro\u00dfe Anwendung hat, die urspr\u00fcnglich nicht darauf ausgelegt ist, umgeschrieben zu werden.<\/p>\n<p>Welche Methoden verwenden wir zur Abtrennung von Microservices?<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"5\"><\/a><\/noindex><b>Erste Methode <\/b>\u2014 bestehende Module als Dienste herauszul\u00f6sen. In dieser Hinsicht hatten wir Gl\u00fcck: Es gab bereits implementierte Dienste, die das WCF-Protokoll verwendeten. Diese waren in separate Assemblies aufgeteilt. Wir haben sie getrennt \u00fcbertragen und jeder Assembly ein kleines Startmodul hinzugef\u00fcgt. Dieses wurde mit der gro\u00dfartigen Topshelf-Bibliothek geschrieben, die es erm\u00f6glicht, die Anwendung sowohl als Dienst als auch als Konsole auszuf\u00fchren. Das ist f\u00fcr die Fehlersuche praktisch, da keine zus\u00e4tzlichen Projekte im L\u00f6sungsansatz erforderlich sind.<\/p>\n<p>Die Dienste waren durch Gesch\u00e4ftslogik miteinander verbunden, da sie gemeinsame Assemblies verwendeten und mit einer gemeinsamen Datenbank arbeiteten. Man konnte sie nicht wirklich als reinrassige Mikrodienste bezeichnen. Dennoch konnten wir diese Dienste separat in unterschiedlichen Prozessen bereitstellen. Das allein reduziert den Einfluss, den sie aufeinander haben, und verringert das Problem mit paralleler Entwicklung und einem einzigen Fehlerpunkt.<\/p>\n<p>Das Hosting mit einer Zeile Code in der Program-Klasse. Die Arbeit mit Topshelf haben wir in eine Hilfsklasse verborgen.<\/p>\n<pre><code class=\"plaintext\">namespace RBA.Services.Accounts.Host\n{\n   internal class Program\n   {\n      private static void Main(string[] args)\n      {\n        HostRunner.Run(\"RBA.Services.Accounts.Host\");\n\n       }\n    }\n}\n<\/code><\/pre>\n<p>\n<noindex><a rel=\"nofollow\" name=\"6\"><\/a><\/noindex><b>Die zweite M\u00f6glichkeit zur Ausgliederung von Mikrodiensten:<\/b> sie zur L\u00f6sung neuer Aufgaben zu erstellen. Wenn dabei das Monolith nicht w\u00e4chst, ist das bereits ein guter Fortschritt, das bedeutet, dass wir auf dem richtigen Weg sind. Um neue Herausforderungen anzugehen, haben wir versucht, separate Dienste zu schaffen. Wo es m\u00f6glich war, haben wir 'kanonischere' Dienste entwickelt, die vollst\u00e4ndig ihre eigene Datenmodellierung und eine separate Datenbank verwalten. <\/p>\n<p>Wie viele andere haben auch wir mit Authentifizierungs- und Autorisierungsdiensten begonnen. Diese eignen sich perfekt daf\u00fcr. Sie sind unabh\u00e4ngig und verf\u00fcgen in der Regel \u00fcber ein separates Datenmodell. Diese Dienste interagieren nicht selbst mit dem Monolithen, sondern nur umgekehrt, wenn der Monolith sie zur L\u00f6sung bestimmter Aufgaben anfragt. Auf diesen Diensten kann man den \u00dcbergang zu einer neuen Architektur beginnen, die Infrastruktur testen und verschiedene Ans\u00e4tze in Bezug auf Netzwerkbibliotheken ausprobieren. In unserer Organisation gibt es keine Teams, die keinen Authentifizierungsdienst erstellen k\u00f6nnten. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"7\"><\/a><\/noindex><b>Der dritte Ansatz zur Herausbildung von Mikrodiensten<\/b>, die wir verwenden, ist f\u00fcr uns etwas spezifisch. Es handelt sich um die Auslagerung von Gesch\u00e4ftslogik aus der UI-Schicht. Unsere Hauptanwendung ist eine Desktop-App, die, wie auch das Backend, in C# geschrieben ist. Die Entwickler haben gelegentlich Fehler gemacht und Teile der Logik, die im Backend existieren und wiederverwendet werden sollten, in die UI ausgelagert. <\/p>\n<p>Ein konkretes Beispiel aus dem Code der UI-Komponente zeigt, dass ein gro\u00dfer Teil dieser L\u00f6sung echte Gesch\u00e4ftslogik enth\u00e4lt, die auch in anderen Prozessen n\u00fctzlich ist, nicht nur f\u00fcr die Erstellung von UI-Formularen. <\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/74c7b90ff94b343816ab3ac2fa0673c6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDie echte Logik in der UI beschr\u00e4nkt sich nur auf die letzten beiden Zeilen. Wir haben sie auf den Server \u00fcbertragen, um die Wiederverwendbarkeit zu erm\u00f6glichen, was die UI reduziert und zu einer korrekten Architektur f\u00fchrt.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"8\"><\/a><\/noindex><b>Der vierte, und wichtigste Weg zur Abgrenzung von Mikrodiensten<\/b>, was eine Modularisierung erm\u00f6glicht \u2013 die Auslagerung bestehender Dienste mit anschlie\u00dfender \u00dcberarbeitung. Wenn wir bestehende Module unver\u00e4ndert \u00fcbernehmen, entspricht das Ergebnis nicht immer den Erwartungen der Entwickler, und der Gesch\u00e4ftsprozess k\u00f6nnte seit der Erstellung der Funktionalit\u00e4t veraltet sein. Durch Refactoring k\u00f6nnen wir neue Gesch\u00e4ftsprozesse unterst\u00fctzen, denn die Anforderungen an Unternehmen \u00e4ndern sich st\u00e4ndig. Wir k\u00f6nnen den Quellcode verbessern, bekannte M\u00e4ngel beseitigen und ein hochwertigeres Datenmodell erstellen. Es ergeben sich viele Vorteile.<\/p>\n<p>Die Trennung von Dienstleistungen mit einer Verarbeitung ist untrennbar mit dem Konzept des begrenzten Kontexts verbunden. Dieses Konzept stammt aus der objektorientierten Gestaltung. Es bezeichnet einen Bereich des Dom\u00e4nenmodells, in dem alle Begriffe einer einheitlichen Sprache eindeutig definiert sind. Betrachten wir das Beispiel des Kontexts von Versicherungen und Rechnungen. Wir haben eine monolithische Anwendung und m\u00fcssen in den Versicherungen mit der Rechnung arbeiten. Wir erwarten, dass der Entwickler in einem anderen Build die bestehende Klasse \u201eRechnung\u201c findet und von der Klasse \u201eVersicherung\u201c darauf verweist, wodurch wir funktionierenden Code erhalten. Das DRY-Prinzip wird eingehalten, was die Aufgabe durch die Nutzung bestehenden Codes beschleunigt.<\/p>\n<p>Letztendlich stellt sich heraus, dass die Kontexte von Rechnungen und Versicherungen miteinander verbunden sind. Wenn neue Anforderungen entstehen, wird diese Verbindung die Entwicklung behindern und die Komplexit\u00e4t der ohnehin schon komplizierten Gesch\u00e4ftslogik erh\u00f6hen. Um dieses Problem zu l\u00f6sen, ist es notwendig, im Code die Grenzen zwischen den Kontexten zu finden und deren Verst\u00f6\u00dfe zu beseitigen. Zum Beispiel k\u00f6nnte es f\u00fcr den Versicherungskontext ausreichend sein, eine 20-stellige Kontonummer der Zentralbank und das Er\u00f6ffnungsdatum des Kontos zu verwenden. <\/p>\n<p>Um diese begrenzten Kontexte voneinander zu trennen und den Prozess der Herausl\u00f6sung von Mikrodiensten aus monolithischen L\u00f6sungen zu beginnen, haben wir den Ansatz verwendet, externe APIs innerhalb der Anwendung zu erstellen. Wenn wir wussten, dass ein bestimmtes Modul ein Mikrodienst werden sollte oder sich im Prozess \u00e4ndern w\u00fcrde, f\u00fchrten wir sofort Aufrufe der Logik, die zu einem anderen eingeschr\u00e4nkten Kontext geh\u00f6rt, \u00fcber externe Calls durch. Zum Beispiel \u00fcber REST oder WCF.<\/p>\n<p>Wir haben f\u00fcr uns entschieden, dass wir keinen Code vermeiden werden, der verteilte Transaktionen erfordert. In unserem Fall war es relativ einfach, diese Regel einzuhalten. Bislang gab es keine Situationen, in denen tats\u00e4chlich strikte verteilte Transaktionen erforderlich waren \u2013 die endg\u00fcltige Konsistenz zwischen den Modulen war v\u00f6llig ausreichend.<\/p>\n<p>Betrachten wir ein konkretes Beispiel. Es gibt das Konzept des Orchestrators \u2014 eine Pipeline, die die Entit\u00e4t \u201eAntrag\u201c verarbeitet. Sie erstellt nacheinander den Kunden, das Konto und die Bankkarte. Wenn der Kunde und das Konto erfolgreich erstellt wurden, die Erstellung der Karte jedoch fehlschl\u00e4gt, wechselt der Antrag nicht in den Status \u201eerfolgreich\u201c und bleibt im Status \u201eKarte nicht erstellt\u201c. Zuk\u00fcnftig wird ein Hintergrundprozess diese Aufgabe \u00fcbernehmen und abschlie\u00dfen. Das System befindet sich f\u00fcr eine gewisse Zeit in einem inkonsistenten Zustand, was f\u00fcr uns jedoch insgesamt akzeptabel ist.<\/p>\n<p>Sollte dennoch eine Situation auftreten, in der wir einen Teil der Daten konsistent speichern m\u00fcssen, werden wir wahrscheinlich einem Service-Zusammenfassung zustimmen, um dies in einem einzigen Prozess zu behandeln. <\/p>\n<p>Betrachten wir das Beispiel der Herausbildung eines Mikrodienstes. Wie k\u00f6nnen wir ihn relativ sicher in die Produktion bringen? In diesem Beispiel haben wir einen separaten Teil des Systems \u2014 das Modul f\u00fcr die Lohnabrechnung, von dem wir einen Teil des Codes in einen Mikrodienst umwandeln m\u00f6chten.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/346af271b0c3f99897d330e56f713f18.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nZun\u00e4chst erstellen wir einen Mikrodienst, indem wir den Code umschreiben. Wir verbessern bestimmte Aspekte, die uns nicht zufrieden stellten. Neue Gesch\u00e4ftsanfragen des Kunden werden umgesetzt. In die Verbindung zwischen UI und Backend f\u00fcgen wir ein API Gateway ein, das die Durchleitung von Aufrufen sicherstellt. <\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/bec8d68f20f3ec53af0cef225a51c2b3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAnschlie\u00dfend setzen wir diese Konfiguration in Betrieb, jedoch im Pilotzustand. Die meisten Nutzer arbeiten weiterhin mit den alten Gesch\u00e4ftsprozessen. F\u00fcr neue Nutzer entwickeln wir eine neue Version der monolithischen Anwendung, die diesen Prozess nicht mehr enth\u00e4lt. Im Grunde genommen funktioniert unsere Verbindung zwischen dem Monolithen und dem Mikrodienst im Pilotmodus.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/27e98812746bb7f142fa3a3c3a03b52f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nBei einem erfolgreichen Pilotprojekt erkennen wir, dass die neue Konfiguration tats\u00e4chlich funktioniert. Wir k\u00f6nnen den alten Monolithen aus der Gleichung entfernen und die neue Konfiguration anstelle der alten L\u00f6sung beibehalten.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/11dcf1d771b57d3921c0aa91b82646e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nInsgesamt nutzen wir nahezu alle bestehenden Methoden zur Aufteilung des Quellcodes des Monolithen. Diese erm\u00f6glichen es uns, die Gr\u00f6\u00dfe der App-Teile zu reduzieren und sie auf neue Bibliotheken zu migrieren, wodurch der Quellcode qualitativ hochwertiger wird.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"9\"><\/a><\/noindex><b><\/p>\n<h3>Arbeiten mit der DB<\/h3>\n<p><\/b><br \/>\nDie Datenbank ist schwieriger zu partitionieren als der Quellcode, da sie nicht nur das aktuelle Schema enth\u00e4lt, sondern auch historische Daten, die sich angesammelt haben.<\/p>\n<p>Unsere Datenbank hatte, wie viele andere, einen weiteren wichtigen Nachteil \u2013 ihre enorme Gr\u00f6\u00dfe. Sie wurde gem\u00e4\u00df der komplexen Gesch\u00e4ftslogik des Monolithen entworfen, und zwischen den Tabellen verschiedener begrenzter Kontexte sind viele Verbindungen entstanden.<\/p>\n<p>In unserem Fall kam zu all den Schwierigkeiten (gro\u00dfe Datenbank, zahlreiche Verbindungen, manchmal unklare Grenzen zwischen den Tabellen) das Problem, das in vielen gro\u00dfen Projekten vorkommt: die Verwendung des Shared-Database-Musters. Daten wurden \u00fcber Views aus Tabellen abgerufen, teilweise repliziert und in andere Systeme geladen, wo diese Replikation ben\u00f6tigt wurde. Dadurch konnten wir die Tabellen nicht in ein separates Schema auslagern, da sie aktiv genutzt wurden.<\/p>\n<p>Bei der Partitionierung hilft uns die zum Code passende Aufteilung in begrenzte Kontexte. Diese gibt uns in der Regel eine recht gute Vorstellung davon, wie wir die Daten auf Datenbankebene aufteilen. Wir verstehen, welche Tabellen zu einem begrenzten Kontext geh\u00f6ren und welche zu einem anderen.<\/p>\n<p>Wir haben zwei globale Ans\u00e4tze zur Datenbanktrennung angewendet: die Trennung bestehender Tabellen und die Trennung mit Umgestaltung.<\/p>\n<p>Die Trennung bestehender Tabellen ist eine Methode, die gut anwendbar ist, wenn die Datenstruktur qualitativ hochwertig ist, den gesch\u00e4ftlichen Anforderungen entspricht und alle Beteiligten zufrieden sind. In diesem Fall k\u00f6nnen wir die bestehenden Tabellen in ein separates Schema auslagern.<\/p>\n<p>Die Trennung mit Umgestaltung ist erforderlich, wenn sich das Gesch\u00e4ftsmodell erheblich ver\u00e4ndert hat und die Tabellen uns nicht mehr zufriedenstellen.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"10\"><\/a><\/noindex><b>Trennung bestehender Tabellen.<\/b> Wir m\u00fcssen festlegen, was wir trennen wollen. Ohne dieses Wissen wird es nicht funktionieren, und hier hilft uns die Trennung begrenzter Kontexte im Code. In der Regel wird klar, welche Tabellen in die Liste zur Trennung aufgenommen werden sollen, wenn wir die Grenzen der Kontexte im Quellcode verstehen.<\/p>\n<p>Stellen Sie sich vor, wir haben eine L\u00f6sung, bei der zwei Module des Monolithen mit einer einzigen Datenbank interagieren. Wir m\u00fcssen sicherstellen, dass nur ein Modul mit den separierbaren Tabellen interagiert, w\u00e4hrend das andere \u00fcber eine API damit kommuniziert. F\u00fcr den Anfang reicht es, wenn nur Schreibzugriffe \u00fcber die API erfolgen. Dies ist eine notwendige Bedingung, um von der Unabh\u00e4ngigkeit der Mikrodienste sprechen zu k\u00f6nnen. Leseverbindungen k\u00f6nnen bestehen bleiben, solange dies kein gr\u00f6\u00dferes Problem darstellt.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/1602637ad752ac055f475cfa45d95e95.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIm n\u00e4chsten Schritt k\u00f6nnen wir den Codeabschnitt, der mit den separierbaren Tabellen arbeitet, mit oder ohne \u00dcberarbeitung in einen separaten Mikrodienst auslagern und ihn in einem eigenen Prozess oder Container ausf\u00fchren. Dies wird ein separater Dienst sein, der eine Verbindung zur Datenbank des Monolithen und zu den Tabellen hat, die nicht direkt zu ihm geh\u00f6ren. Der Monolith greift weiterhin lesend auf den separierbaren Teil zu. <\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/36011f4e6be4f6a2f19f2f074b645dcb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSp\u00e4ter werden wir diese Verbindung entfernen, das hei\u00dft, auch die Lesezugriffe des monolithischen Anwendungs auf die separierbaren Tabellen werden auf die API umgestellt.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/290f91bbfccac2a4b384078e4cf4e337.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAls N\u00e4chstes isolieren wir aus der gesamten Datenbank die Tabellen, mit denen nur der neue Mikrodienst arbeitet. Wir k\u00f6nnen die Tabellen in ein separates Schema oder sogar in eine separate physische Datenbank auslagern. Es besteht eine Lesekommunikation zwischen dem Mikrodienst und der Datenbank des Monolithen, aber das ist nicht problematisch, in dieser Konfiguration kann er lange Zeit bestehen bleiben.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/ab947ac6a38ffbccd4e2b51103aef609.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDer letzte Schritt besteht darin, alle Verbindungen vollst\u00e4ndig zu entfernen. In diesem Fall ben\u00f6tigen wir m\u00f6glicherweise einen Datenmigrationsprozess von der Hauptdatenbank. Manchmal m\u00f6chten wir in mehreren Datenbanken replizierbare Daten oder Verzeichnisse aus externen Systemen wiederverwenden. Das kommt bei uns gelegentlich vor.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/f40cf17dd56b9575751e370c44f08344.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<noindex><a rel=\"nofollow\" name=\"11\"><\/a><\/noindex><b>Abtrennung mit Umgestaltung.<\/b> Diese Methode \u00e4hnelt der ersten, jedoch in umgekehrter Reihenfolge. Wir erstellen sofort eine neue Datenbank und einen neuen Mikrodienst, der \u00fcber die API mit dem Monolithen interagiert. Dabei bleibt jedoch eine Reihe von Datenbanktabellen bestehen, die wir in Zukunft entfernen m\u00f6chten. Diese werden nicht mehr ben\u00f6tigt, in dem neuen Modell haben wir sie ersetzt.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/c94932033e47cfa1fd56595ab9a19246.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDamit dieses Schema funktioniert, ben\u00f6tigen wir wahrscheinlich einen \u00dcbergangszeitraum.<\/p>\n<p>Es gibt zwei m\u00f6gliche Ans\u00e4tze.<\/p>\n<p><b>Erster<\/b>: Wir duplizieren alle Daten in der alten und neuen Datenbank. In diesem Fall entsteht Datenredundanz, was zu Synchronisierungsproblemen f\u00fchren kann. Aber wir k\u00f6nnen zwei verschiedene Kunden bedienen. Einer arbeitet mit der neuen Version, der andere mit der alten.<\/p>\n<p><b>Zweite<\/b>: Wir teilen die Daten nach einem bestimmten Gesch\u00e4ftskriterium auf. Zum Beispiel hatten wir in unserem System 5 Produkte, die in der alten Datenbank gespeichert waren. Das sechste Produkt f\u00fcgen wir im Rahmen einer neuen Gesch\u00e4ftsanforderung in die neue DB ein. Doch wir ben\u00f6tigen ein API-Gateway, das diese Daten synchronisiert und dem Kunden zeigt, woher und was er abrufen kann.<\/p>\n<p>Beide Ans\u00e4tze sind praktikabel, w\u00e4hlen Sie je nach Situation.<\/p>\n<p>Sobald wir sicher sind, dass alles funktioniert, kann der Teil des Monolithen, der mit den alten DB-Strukturen arbeitet, abgeschaltet werden. <\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/973bf5015bdf49a290a5b901f89628cc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDer letzte Schritt wird die L\u00f6schung der alten Datenstrukturen sein. <\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/fe83acc07077b7eb3717138e3c20c005.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nZusammenfassend l\u00e4sst sich sagen, dass wir Probleme mit der DB haben: Es ist schwieriger, damit zu arbeiten als mit dem Quellcode, das Trennen ist komplizierter, aber es ist m\u00f6glich und notwendig. Wir haben einige Methoden gefunden, die es erm\u00f6glichen, dies relativ sicher zu tun, schlie\u00dflich ist es einfacher, mit Daten einen Fehler zu machen als mit dem Quellcode. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"12\"><\/a><\/noindex><b><\/p>\n<h3>Arbeiten mit Quellcode<\/h3>\n<p><\/b><br \/>\nSo sah das Quellcode-Schema aus, als wir mit der Analyse des monolithischen Projekts begannen.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/a6d886e37117ccf8f63106d6616aa653.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEs l\u00e4sst sich grob in drei Schichten unterteilen. Dies ist die Schicht der ausf\u00fchrbaren Module, Plugins, Dienste und einzelner Aktivit\u00e4ten. Tats\u00e4chlich waren dies die Einstiegspunkte innerhalb der monolithischen L\u00f6sung. Alle waren fest mit der Schicht Common verbunden. Darin befand sich die Gesch\u00e4ftslogik, die von den Diensten gemeinsam genutzt wurde, sowie zahlreiche Verbindungen. Jeder Dienst und jedes Plugin verwendete bis zu 10 und mehr Common-Bibliotheken, abh\u00e4ngig von ihrer Gr\u00f6\u00dfe und dem Gewissen der Entwickler.<\/p>\n<p>Wir hatten das Gl\u00fcck, Infrastruktur-Bibliotheken zu haben, die separat genutzt werden konnten. <\/p>\n<p>Manchmal kam es vor, dass einige Common-Objekte eigentlich nicht zu dieser Schicht geh\u00f6rten, sondern Infrastruktur-Bibliotheken waren. Dies wurde durch Umbenennung gel\u00f6st.<\/p>\n<p>Die gr\u00f6\u00dfte Besorgnis galt den begrenzten Kontexten. Es kam vor, dass 3-4 Kontexte in einer gemeinsamen Build-Version vermischt wurden und sich gegenseitig im Rahmen derselben Gesch\u00e4ftsfunktionen verwendeten. Es war notwendig zu verstehen, wo diese getrennt werden k\u00f6nnen und an welchen Grenzen, sowie was im Anschluss mit der Zuordnung dieser Trennung zu den Ursprungs-Code-Builds zu tun ist.<\/p>\n<p>Wir haben mehrere Regeln f\u00fcr den Prozess der Code-Trennung formuliert.<\/p>\n<p><b>Erstens<\/b>: Wir wollten keine gemeinsame Nutzung der Gesch\u00e4ftslogik zwischen den Diensten, Aktivit\u00e4ten und Plugins mehr. Unser Ziel war es, die Gesch\u00e4ftslogik innerhalb der Mikrodienste unabh\u00e4ngig zu gestalten. Idealerweise werden Mikrodienste als v\u00f6llig eigenst\u00e4ndige Services betrachtet. Ich halte diesen Ansatz jedoch f\u00fcr etwas verschwenderisch, da es auch schwierig ist, ihn zu erreichen. Beispielsweise werden Dienste, die in C# entwickelt werden, immer mit der Standardbibliothek verbunden sein. Unser System ist in C# geschrieben, andere Technologien mussten wir bisher nicht einsetzen. Daher haben wir entschieden, dass wir es uns leisten k\u00f6nnen, gemeinsame technische Assemblierungen zu nutzen. Wichtig ist nur, dass diese keinerlei Fragmente der Gesch\u00e4ftslogik enthalten. Wenn Sie ein n\u00fctzliches Wrapper \u00fcber das ORM haben, das Sie verwenden, ist es sehr kostspielig, dies von einem Dienst zum anderen zu kopieren.<\/p>\n<p>Unser Team ist begeistert von objektorientiertem Design, daher passt die \"Zwiebelarchitektur\" perfekt zu uns. Die Grundlage unserer Dienste ist nicht die Datenauszugsschicht, sondern eine Sammlung mit der Domainlogik, die nur Gesch\u00e4ftslogik enth\u00e4lt und keine Bindungen zur Infrastruktur hat. Damit k\u00f6nnen wir die Domainzusammenstellung unabh\u00e4ngig weiterentwickeln, um Probleme im Zusammenhang mit Frameworks zu l\u00f6sen.<\/p>\n<p>In dieser Phase stie\u00dfen wir auf das erste ernsthafte Problem. Der Dienst sollte sich auf ein domain\u00fcbergreifendes Assembly beziehen, wobei wir die Logik unabh\u00e4ngig gestalten wollten, doch dabei stellte uns das DRY-Prinzip vor gro\u00dfe Herausforderungen. Die Entwickler wollten zur Vermeidung von Duplikaten Klassen aus benachbarten Assemblies wiederverwenden, was dazu f\u00fchrte, dass die Domains erneut miteinander verkn\u00fcpft wurden. Wir analysierten die Ergebnisse und kamen zu dem Schluss, dass das Problem m\u00f6glicherweise auch im Bereich der Architektur des Quellcode-Repositorys lag. Wir hatten ein gro\u00dfes Repository, in dem sich alles Quellmaterial befand. Die Erstellung einer Solution f\u00fcr das gesamte Projekt war auf unserem lokalen Ger\u00e4t \u00e4u\u00dferst kompliziert. Daher wurden f\u00fcr verschiedene Teile des Projekts separate, kleinere Solutions erstellt, und nichts sprach dagegen, dass man eine beliebige Common- oder Domain-Assembly hinzuf\u00fcgte und sie wiederverwendete. Das einzige Tool, das uns daran hinderte, war das Code-Review. Aber manchmal versagte auch dieses.<\/p>\n<p>So haben wir begonnen, auf ein Modell mit separaten Repositories umzustellen. Die Gesch\u00e4ftslogik flie\u00dft nicht mehr von einem Service zum anderen, und die Dom\u00e4nen sind tats\u00e4chlich unabh\u00e4ngig geworden. Eingeschr\u00e4nkte Kontexte werden nun klarer unterst\u00fctzt. Wie nutzen wir dabei die Infrastruktur-Bibliotheken erneut? Wir haben sie in ein separates Repository ausgegliedert, dann in Nuget-Pakete verpackt und in Artifactory abgelegt. Bei jeder \u00c4nderung erfolgt automatisch die Erstellung und Ver\u00f6ffentlichung.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/8ddbc750dc7c6d397a459acf7825de90.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nUnsere Services beziehen sich auf interne Infrastruktur-Pakete ebenso wie auf externe. Die externen Bibliotheken laden wir \u00fcber Nuget herunter. F\u00fcr die Arbeit mit Artifactory, wo wir diese Pakete abgelegt haben, haben wir zwei Paketmanager eingesetzt. In kleinen Repositories haben wir ebenfalls Nuget genutzt. In Repositories mit mehreren Services haben wir Paket verwendet, das eine gr\u00f6\u00dfere Konsistenz der Versionen zwischen den Modulen gew\u00e4hrleistet.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/672a25a70a481bff68baebe963184ccd.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDurch die Arbeit am Quellcode haben wir, indem wir die Architektur etwas ver\u00e4ndert und Repositories getrennt haben, unsere Services unabh\u00e4ngiger gemacht.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"13\"><\/a><\/noindex><b><\/p>\n<h3>Infrastrukturprobleme<\/h3>\n<p><\/b><br \/>\nDie meisten Probleme beim Wechsel zu Microservices h\u00e4ngen mit der Infrastruktur zusammen. Sie ben\u00f6tigen automatisierte Bereitstellungen und neue Bibliotheken, um die Infrastruktur effizient zu betreiben.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"16\"><\/a><\/noindex><b>Manuelle Installation in Umgebungen<\/b><\/p>\n<p>Urspr\u00fcnglich haben wir die Umgebungen manuell eingerichtet. Um diesen Prozess zu automatisieren, haben wir eine CI\/CD-Pipeline eingerichtet. Wir haben uns f\u00fcr den kontinuierlichen Bereitstellungsprozess entschieden, da die kontinuierliche Bereitstellung f\u00fcr uns aus gesch\u00e4ftlichen Gr\u00fcnden momentan nicht akzeptabel ist. Daher erfolgt das Deployment per Knopfdruck, w\u00e4hrend die Tests automatisch ablaufen.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/0fc092326a48813398c6f3a031197bab.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWir nutzen Atlassian, Bitbucket zur Speicherung des Quellcodes und Bamboo f\u00fcr den Build-Prozess. Wir schreiben gerne Buildscripte in Cake, da es sich um dasselbe C# handelt. In Artifactory werden bereits fertige Pakete hinterlegt, und Ansible wird automatisch auf die Testserver \u00fcbertragen, sodass diese sofort getestet werden k\u00f6nnen.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/fcc743cfaa4a24b906ceeb40ec1ba0a0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<noindex><a rel=\"nofollow\" name=\"14\"><\/a><\/noindex><b><\/p>\n<h3>Getrennte Protokollierung<\/h3>\n<p><\/b><br \/>\nEines der urspr\u00fcnglichen Ziele des Monolithen war die gemeinsame Protokollierung. Wir mussten auch verstehen, wie wir mit den separaten Logs umgehen, die auf den Datentr\u00e4gern liegen. Die Logs werden in Textdateien geschrieben. Wir haben uns entschieden, den Standard-ELK-Stack zu verwenden. Statt direkt \u00fcber Provider in ELK zu schreiben, haben wir beschlossen, die Textlogs zu \u00fcberarbeiten und die Trace-ID als Identifikator hinzuzuf\u00fcgen, indem wir den Servicenamen erg\u00e4nzen, damit diese Logs sp\u00e4ter analysiert werden k\u00f6nnen.<\/p>\n<p><img decoding=\"async\" alt=\"Der \u00dcbergang von Monolithen zu Mikrodiensten: Geschichte und Praxis\" src=\"\/wp-content\/uploads\/2019\/07\/8e58c66ac134e65abe34b59939f31483.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nMit Filebeat k\u00f6nnen wir unsere Logs von <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/de\/server\/\"   title=\"Server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1338\">Server<\/a>sammeln, sie dann transformieren, \u00fcber Kibana Abfragen im UI erstellen und nachverfolgen, wie die Aufrufe zwischen den Services abliefen. Dabei hilft die Trace-ID erheblich.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"15\"><\/a><\/noindex><b><\/p>\n<h3>Testen und Debuggen von verbundenen Diensten<\/h3>\n<p><\/b><br \/>\nAnfangs hatten wir nicht ganz verstanden, wie wir die entwickelten Dienste optimieren sollten. Bei einem Monolithen war alles einfach, wir konnten ihn auf einer lokalen Maschine starten. Zun\u00e4chst haben wir auch mit Mikrodiensten versucht, dies zu tun, aber manchmal erfordert der vollst\u00e4ndige Start eines Mikrodienstes, dass auch mehrere andere gestartet werden, was unpraktisch ist. Wir haben erkannt, dass wir zu einem Modell \u00fcbergehen m\u00fcssen, bei dem wir nur den Dienst oder die Dienste auf der lokalen Maschine lassen, die wir debuggen m\u00f6chten. Die anderen Dienste laufen von Servern, die in der Konfiguration mit der Produktionsumgebung \u00fcbereinstimmen. Nach dem Debugging werden bei jedem Test auf dem Testserver nur die ge\u00e4nderten Dienste bereitgestellt. So wird die L\u00f6sung in der Form getestet, in der sie sp\u00e4ter in der Produktion verf\u00fcgbar sein wird.<\/p>\n<p>Es gibt Server, auf denen nur die Produktionsversionen der Dienste installiert sind. Diese Server sind n\u00f6tig f\u00fcr den Fall von Vorf\u00e4llen, zur \u00dcberpr\u00fcfung der Bereitstellung vor dem Deployment und f\u00fcr interne Schulungen.<\/p>\n<p>Wir haben einen automatisierten Testprozess mit der beliebten SpecFlow-Bibliothek eingef\u00fchrt. Die Tests werden direkt nach dem Deployment \u00fcber Ansible automatisch mit NUnit ausgef\u00fchrt. Wenn die Aufgaben vollst\u00e4ndig automatisiert sind, ist kein manuelles Testen erforderlich. Manchmal ist jedoch zus\u00e4tzliches manuelles Testen notwendig. Um zu bestimmen, welche Tests f\u00fcr eine bestimmte Aufgabe ausgef\u00fchrt werden sollen, verwenden wir Tags in Jira.<\/p>\n<p>Zudem ist der Bedarf an Lasttests gestiegen; zuvor wurden diese nur in seltenen F\u00e4llen durchgef\u00fchrt. F\u00fcr die Ausf\u00fchrung der Tests nutzen wir JMeter, zur Speicherung verwenden wir InfluxDB, und f\u00fcr die grafische Darstellung des Prozesses kommt Grafana zum Einsatz.<\/p>\n<p><b><\/p>\n<h3>Was haben wir erreicht?<\/h3>\n<p><\/b><br \/>\nErstens haben wir das Konzept des \u201eRelease\u201c abgeschafft. Die monatelangen gro\u00dfen Releases, bei denen dieses Monstrum in der Produktionsumgebung ausgerollt wurde und zeitweise die Gesch\u00e4ftsprozesse lahmlegte, geh\u00f6ren der Vergangenheit an. Jetzt f\u00fchren wir durchschnittlich alle 1,5 Tage Deployments durch, gruppieren diese, da sie nach Abstimmung in Betrieb genommen werden.<\/p>\n<p>In unserem System gibt es keine kritischen Fehler. Wenn wir einen Microservice mit einem Fehler bereitstellen, wird die damit verbundene Funktionalit\u00e4t beeintr\u00e4chtigt, w\u00e4hrend alle anderen Funktionen unber\u00fchrt bleiben. Das verbessert die Benutzererfahrung erheblich.<\/p>\n<p>Wir k\u00f6nnen das Bereitstellungsschema steuern. Es ist m\u00f6glich, Gruppen von Services von der restlichen L\u00f6sung zu trennen, wenn dies erforderlich ist.<\/p>\n<p>Dar\u00fcber hinaus haben wir das Problem mit langen Warteschlangen bei Anpassungen erheblich verringert. Wir haben separate Produktteams eingerichtet, die unabh\u00e4ngig an bestimmten Services arbeiten. Hier eignet sich der Scrum-Prozess gut. Ein bestimmtes Team kann einen eigenen Produktinhaber haben, der Aufgaben f\u00fcr das Team festlegt. <\/p>\n<p><b><\/p>\n<h3>Zusammenfassung<\/h3>\n<p><\/b><\/p>\n<ul>\n<li>Microservices sind gut geeignet, um komplexe Systeme zu dekomponieren. Im Prozess beginnen wir zu verstehen, was in unserem System vorhanden ist, welche eingeschr\u00e4nkten Kontexte bestehen und wo deren Grenzen liegen. Dies erm\u00f6glicht es, Anpassungen korrekt auf die Module zu verteilen und Verwirrung im Code zu vermeiden. <\/li>\n<li>Mikroservices bieten organisatorische Vorteile. Oft wird nur \u00fcber sie als Architektur gesprochen, jedoch dient jede Architektur dem Zweck, die Gesch\u00e4ftsbed\u00fcrfnisse zu erf\u00fcllen, und nicht nur ihrer eigenen Existenz willen. Daher k\u00f6nnen wir sagen, dass Mikroservices besonders geeignet sind, um Aufgaben in kleinen Teams zu bew\u00e4ltigen, insbesondere da Scrum derzeit sehr beliebt ist.<\/li>\n<li>Die Aufteilung ist ein iterativer Prozess. Man kann eine Anwendung nicht einfach in Mikroservices teilen. Das resultierende Produkt wird wahrscheinlich nicht funktionsf\u00e4hig sein. Bei der Herausbildung von Mikroservices ist es ratsam, bestehende Legacy-Systeme zu \u00fcberarbeiten, um sie in einen Code umzuwandeln, der unseren Anforderungen bez\u00fcglich Funktionalit\u00e4t und Geschwindigkeit besser entspricht.\n<p><i>Eine kleine Warnung:<\/i> Die Kosten f\u00fcr den \u00dcbergang zu Mikrodiensten sind betr\u00e4chtlich. Allein die L\u00f6sung von Infrastrukturproblemen hat viel Zeit in Anspruch genommen. Daher, wenn Sie eine kleine Anwendung haben, die kein spezifisches Skalierung erfordert, und wenn es nicht viele Kunden gibt, die um die Aufmerksamkeit und Zeit Ihres Teams k\u00e4mpfen, dann sind Mikrodienste m\u00f6glicherweise nicht das, was Sie heute brauchen. Es ist durchaus kostspielig. Wenn Sie mit Mikrodiensten beginnen, werden die Anfangskosten h\u00f6her sein, als wenn dasselbe Projekt als Monolith entwickelt wird. <\/p>\n<p>P.S. Eine emotionalere Erz\u00e4hlung (als ob sie pers\u00f6nlich f\u00fcr Sie w\u00e4re) - zu <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=qTNbx18DzpQ\">\u00fcber diesen Link verf\u00fcgbar<\/a><\/noindex>. <br \/>\nHier ist die vollst\u00e4ndige Version des Berichts.<\/li>\n<\/ul>\n<p>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/raiffeisenbank\/blog\/458404\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000. \u041f\u0435\u0440\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 Visual Basic 6. \u0421 \u0442\u0435\u0447\u0435\u043d\u0438\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430 \u044d\u0442\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a IDE [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":26858,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-35906","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000. \u041f\u0435\u0440\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 Visual Basic 6. \u0421 \u0442\u0435\u0447\u0435\u043d\u0438\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430 \u044d\u0442\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a IDE\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043e\u0442 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u043a \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c: \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000. \u041f\u0435\u0440\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 Visual Basic 6. \u0421 \u0442\u0435\u0447\u0435\u043d\u0438\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430 \u044d\u0442\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a IDE\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:07:29+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:07:29+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Von Monolithen zu Mikrodiensten: Geschichte und Praxis | ProHoster","description":"In diesem Artikel werde ich dar\u00fcber berichten, wie das Projekt, an dem ich arbeite, sich von einem gro\u00dfen Monolithen in eine Reihe von Mikrodiensten verwandelte. Das Projekt hat seine Geschichte bereits vor langer Zeit begonnen, zu Beginn der 2000er Jahre. Die ersten Versionen wurden in Visual Basic 6 geschrieben. Im Laufe der Zeit wurde klar, dass die Entwicklung in dieser Sprache in Zukunft schwer zu unterst\u00fctzen sein w\u00fcrde, da die IDE","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043e\u0442 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u043a \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c: \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 | ProHoster","og:description":"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000. \u041f\u0435\u0440\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 Visual Basic 6. \u0421 \u0442\u0435\u0447\u0435\u043d\u0438\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430 \u044d\u0442\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a IDE","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:07:29+00:00","article:modified_time":"2019-10-31T19:07:29+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"35906","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-02-09 17:04:56","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:54:38","updated":"2026-02-09 17:04:56"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/35906","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=35906"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/35906\/revisions"}],"predecessor-version":[{"id":158582,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/35906\/revisions\/158582"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/26858"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=35906"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=35906"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=35906"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}