NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Sie haben Monate damit verbracht, Ihren Monolithen in Microservices umzugestalten, und schließlich sind alle zusammengekommen, um den Schalter umzulegen. Sie gehen auf die erste Webseite... und nichts passiert. Sie laden es neu – und wieder nichts Gutes, die Seite ist so langsam, dass sie mehrere Minuten lang nicht reagiert. Was ist passiert?

In seinem Vortrag wird Jimmy Bogard eine „Post-Mortem“-Untersuchung einer realen Microservice-Katastrophe durchführen. Er wird die von ihm entdeckten Modellierungs-, Entwicklungs- und Produktionsprobleme zeigen und wie sein Team den neuen verteilten Monolithen langsam in das endgültige Bild der Vernunft verwandelte. Obwohl es unmöglich ist, Entwurfsfehler vollständig zu verhindern, können Sie Probleme zumindest frühzeitig im Entwurfsprozess erkennen, um sicherzustellen, dass das Endprodukt ein zuverlässiges verteiltes System wird.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Hallo zusammen, ich bin Jimmy und heute erfahren Sie, wie Sie beim Aufbau von Microservices Megakatastrophen vermeiden können. Dies ist die Geschichte einer Firma, für die ich etwa anderthalb Jahre lang gearbeitet habe, um zu verhindern, dass ihr Schiff mit einem Eisberg kollidiert. Um diese Geschichte richtig zu erzählen, müssen wir in die Vergangenheit reisen und darüber sprechen, wo dieses Unternehmen gegründet wurde und wie seine IT-Infrastruktur im Laufe der Zeit gewachsen ist. Um die Namen der Unschuldigen an dieser Katastrophe zu schützen, habe ich den Namen dieser Firma in Bell Computers geändert. Die nächste Folie zeigt, wie die IT-Infrastruktur solcher Unternehmen Mitte der 90er Jahre aussah. Dies ist eine typische Architektur eines großen universellen fehlertoleranten HP Tandem Mainframe-Servers für den Betrieb eines Computer-Hardware-Geschäfts.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Sie mussten ein System zur Verwaltung aller Bestellungen, Verkäufe, Retouren, Produktkataloge und des Kundenstamms aufbauen und entschieden sich daher für die damals gängigste Mainframe-Lösung. Dieses riesige System enthielt alle möglichen Informationen über das Unternehmen und jede Transaktion wurde über diesen Großrechner abgewickelt. Sie legten alles auf eine Karte und dachten, das sei normal. Lediglich Versandkataloge und telefonische Bestellungen sind hier nicht enthalten.

Mit der Zeit wurde das System immer größer und es sammelte sich eine riesige Menge Müll darin an. Außerdem ist COBOL nicht die ausdrucksstärkste Sprache der Welt, sodass das System am Ende ein großes, monolithisches Stück Schrott war. Im Jahr 2000 stellten sie fest, dass viele Unternehmen über Websites verfügten, über die sie nahezu alle ihre Geschäfte abwickelten, und beschlossen, ihre erste kommerzielle Dotcom-Website zu erstellen.

Das ursprüngliche Design sah ziemlich gut aus und bestand aus einer Top-Level-Site bell.com und einer Reihe von Subdomains für einzelne Anwendungen: Catalog.bell.com, Accounts.bell.com, Orders.bell.com, Produktsuche Search.bell. com. Jede Subdomäne nutzte das ASP.Net 1.0-Framework und ihre eigenen Datenbanken und alle kommunizierten mit dem System-Backend. Alle Bestellungen wurden jedoch weiterhin in einem einzigen riesigen Großrechner verarbeitet und ausgeführt, in dem der gesamte Müll verblieb, das Frontend jedoch aus separaten Websites mit einzelnen Anwendungen und separaten Datenbanken bestand.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Der Entwurf des Systems sah also ordentlich und logisch aus, aber das tatsächliche System war wie auf der nächsten Folie dargestellt.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Alle Elemente adressierten Aufrufe untereinander, griffen auf APIs zu, eingebettete DLLs von Drittanbietern und Ähnliches. Es kam oft vor, dass Versionskontrollsysteme den Code einer anderen Person schnappten, ihn in das Projekt schoben und dann alles kaputt ging. MS SQL Server 2005 verwendete das Konzept von Linkservern, und obwohl ich die Pfeile auf der Folie nicht gezeigt habe, kommunizierten alle Datenbanken auch miteinander, denn es ist nichts Falsches daran, Tabellen basierend auf Daten zu erstellen, die aus mehreren Datenbanken stammen.

Da es nun eine gewisse Trennung zwischen den verschiedenen logischen Bereichen des Systems gab, kam es zu verteilten Schmutzklumpen, wobei der größte Teil des Mülls immer noch im Mainframe-Backend verblieb.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Das Lustige war, dass dieser Großrechner von Konkurrenten von Bell Computers gebaut wurde und immer noch von deren technischen Beratern gewartet wurde. Überzeugt von der unbefriedigenden Leistung seiner Anwendungen, beschloss das Unternehmen, diese abzuschaffen und das System neu zu gestalten.

Die bestehende Anwendung befand sich seit 15 Jahren in der Produktion, was einen Rekord für ASP.Net-basierte Anwendungen darstellt. Der Dienst nahm Aufträge aus der ganzen Welt an und der Jahresumsatz mit dieser einzigen Anwendung erreichte eine Milliarde Dollar. Ein erheblicher Teil des Gewinns wurde von der Website bell.com erwirtschaftet. An Black Fridays erreichte die Zahl der über die Website aufgegebenen Bestellungen mehrere Millionen. Allerdings erlaubte die bestehende Architektur keine Weiterentwicklung, da die starren Verbindungen der Systemelemente praktisch keine Änderungen am Dienst zuließen.

Das größte Problem bestand darin, dass es nicht möglich war, eine Bestellung in einem Land aufzugeben, sie in einem anderen zu bezahlen und sie in ein drittes Land zu versenden, obwohl ein solches Handelssystem in globalen Unternehmen weit verbreitet ist. Da die bestehende Website dies nicht zuließ, mussten sie diese Bestellungen telefonisch annehmen und aufgeben. Dies führte dazu, dass das Unternehmen zunehmend über eine Änderung der Architektur nachdachte, insbesondere über die Umstellung auf Microservices.

Sie haben die kluge Entscheidung getroffen, sich bei anderen Unternehmen umzusehen, wie sie ein ähnliches Problem gelöst haben. Eine dieser Lösungen war die Netflix-Service-Architektur, die aus Microservices besteht, die über eine API und eine externe Datenbank verbunden sind.

Das Management von Bell Computers beschloss, eine solche Architektur unter Einhaltung bestimmter Grundprinzipien aufzubauen. Erstens eliminierten sie die Datenduplizierung durch den Einsatz eines gemeinsamen Datenbankansatzes. Es wurden keine Daten gesendet, im Gegenteil, jeder, der sie benötigte, musste sich an eine zentrale Quelle wenden. Darauf folgten Isolation und Autonomie – jeder Dienst war unabhängig von den anderen. Sie entschieden sich dafür, die Web-API für absolut alles zu verwenden – ob Sie Daten abrufen oder Änderungen an einem anderen System vornehmen wollten, alles wurde über die Web-API erledigt. Die letzte große Sache war ein neuer Mainframe namens „Bell on Bell“ im Gegensatz zum „Bell“-Mainframe, der auf der Hardware der Konkurrenz basierte.

Also haben sie im Laufe von 18 Monaten das System um diese Kernprinzipien herum aufgebaut und es zur Vorproduktion gebracht. Als die Entwickler nach dem Wochenende wieder an die Arbeit gingen, kamen sie zusammen und schalteten alle Server ein, mit denen das neue System verbunden war. 18 Monate Arbeit, Hunderte Entwickler, modernste Bell-Hardware – und kein positives Ergebnis! Dies hat viele Leute enttäuscht, da sie dieses System viele Male auf ihren Laptops ausgeführt haben und alles in Ordnung war.

Sie waren klug, ihr ganzes Geld in die Lösung dieses Problems zu stecken. Sie haben die modernsten Server-Racks mit Switches installiert, Gigabit-Glasfaserkabel verwendet, die leistungsstärkste Server-Hardware mit wahnsinnig viel RAM, alles angeschlossen, konfiguriert – und wieder nichts! Dann begannen sie zu vermuten, dass Timeouts der Grund sein könnten, also gingen sie in alle Webeinstellungen, alle API-Einstellungen und aktualisierten die gesamte Timeout-Konfiguration auf die Maximalwerte, sodass sie nur noch warten konnten, bis etwas passierte zum Ort. Sie warteten und warteten und warteten neuneinhalb Minuten, bis die Website endlich geladen wurde.

Danach wurde ihnen klar, dass die aktuelle Situation einer gründlichen Analyse bedarf, und sie luden uns ein. Das erste, was wir herausfanden, war, dass in den gesamten 18 Monaten der Entwicklung kein einziges echtes „Mikro“ entstanden ist – alles wurde nur größer. Danach begannen wir mit dem Schreiben einer Obduktion, auch bekannt als „Regretrospektive“ oder „traurige Retrospektive“, auch bekannt als „Blame Storm“, ähnlich einem „Brainstorm“, um die Ursache der Katastrophe zu verstehen.

Wir hatten mehrere Hinweise, einer davon war die vollständige Verkehrssättigung zum Zeitpunkt des API-Aufrufs. Wenn Sie eine monolithische Servicearchitektur verwenden, können Sie sofort erkennen, was genau schief gelaufen ist, da Sie über einen einzigen Stack-Trace verfügen, der alles meldet, was den Fehler verursacht haben könnte. Für den Fall, dass eine Reihe von Diensten gleichzeitig auf dieselbe API zugreifen, gibt es keine Möglichkeit, die Ablaufverfolgung zu verfolgen, außer die Verwendung zusätzlicher Netzwerküberwachungstools wie WireShark, mit denen Sie eine einzelne Anfrage untersuchen und herausfinden können, was während ihrer Implementierung passiert ist. Also nahmen wir eine Webseite und verbrachten fast zwei Wochen damit, die Puzzleteile zusammenzusetzen, sie mehrmals aufzurufen und zu analysieren, wozu jedes einzelne Ergebnis führte.
Guck auf dieses Bild. Es zeigt, dass eine externe Anfrage den Dienst dazu veranlasst, viele interne Anrufe zu tätigen, die zurückkommen. Es stellt sich heraus, dass jeder interne Anruf zusätzliche Sprünge macht, um diese Anfrage unabhängig bedienen zu können, da er sich nirgendwo anders wenden kann, um die erforderlichen Informationen zu erhalten. Dieses Bild sieht aus wie eine bedeutungslose Kaskade von Aufrufen, da die externe Anforderung nahezu endlos weitere Dienste aufruft, die weitere Zusatzdienste usw. aufrufen.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Die grüne Farbe in diesem Diagramm zeigt einen Halbkreis, in dem sich Dienste gegenseitig aufrufen – Dienst A ruft Dienst B auf, Dienst B ruft Dienst C auf und ruft erneut Dienst A auf. Als Ergebnis erhalten wir einen „verteilten Deadlock“. Eine einzige Anfrage erzeugte tausend Netzwerk-API-Aufrufe, und da das System nicht über integrierte Fehlertoleranz und Schleifenschutz verfügte, schlug die Anfrage fehl, wenn auch nur einer dieser API-Aufrufe fehlschlug.

Wir haben etwas nachgerechnet. Jeder API-Aufruf hatte ein SLA von nicht mehr als 150 ms und eine Verfügbarkeit von 99,9 %. Eine Anfrage verursachte 200 verschiedene Aufrufe und im besten Fall konnte die Seite in 200 x 150 ms = 30 Sekunden angezeigt werden. Das war natürlich nicht gut. Wenn wir die Betriebszeit von 99,9 % mit 200 multiplizieren, erhalten wir eine Verfügbarkeit von 0 %. Es stellt sich heraus, dass diese Architektur von Anfang an zum Scheitern verurteilt war.

Wir haben die Entwickler gefragt, warum sie dieses Problem nach 18 Monaten Arbeit nicht erkannt haben? Es stellte sich heraus, dass sie nur das SLA für den von ihnen ausgeführten Code zählten, aber wenn ihr Dienst einen anderen Dienst aufrief, zählten sie diese Zeit nicht in ihrem SLA. Alles, was innerhalb eines Prozesses gestartet wurde, hielt sich an den Wert von 150 ms, Zugriffe auf andere Serviceprozesse erhöhten die Gesamtverzögerung jedoch um ein Vielfaches. Die erste Lektion lautete: „Haben Sie die Kontrolle über Ihr SLA oder hat das SLA die Kontrolle über Sie?“ In unserem Fall war es Letzteres.

Als nächstes entdeckten wir, dass sie zwar über das von Peter Deitch und James Gosling formulierte Konzept der verteilten Computer-Missverständnisse Bescheid wussten, den ersten Teil jedoch ignorierten. Darin heißt es, dass die Aussagen „das Netzwerk ist zuverlässig“, „keine Latenz“ und „unendlicher Durchsatz“ falsche Vorstellungen seien. Weitere Missverständnisse sind die Aussagen „Das Netzwerk ist sicher“, „Die Topologie ändert sich nie“, „Es gibt immer nur einen Administrator“, „Die Kosten für die Datenübertragung betragen Null“ und „Das Netzwerk ist homogen“.
Sie haben einen Fehler gemacht, weil sie ihren Dienst auf lokalen Rechnern getestet und sich nie mit externen Diensten verbunden haben. Bei der lokalen Entwicklung und Verwendung eines lokalen Caches kam es nie zu Netzwerk-Hops. In den 18 Monaten der Entwicklung haben sie sich kein einziges Mal gefragt, was passieren könnte, wenn externe Dienste betroffen wären.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Wenn Sie sich die Servicegrenzen im vorherigen Bild ansehen, können Sie erkennen, dass sie alle falsch sind. Es gibt viele Quellen, die Ratschläge zur Definition von Servicegrenzen geben, und die meisten machen es falsch, wie Microsoft auf der nächsten Folie.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Dieses Bild stammt aus dem MS-Blog zum Thema „How to build microservices“. Dies zeigt eine einfache Webanwendung, einen Block Geschäftslogik und eine Datenbank. Die Anfrage kommt direkt, es gibt wahrscheinlich einen Server für das Web, einen Server für das Unternehmen und einen für die Datenbank. Wenn Sie den Verkehr erhöhen, ändert sich das Bild ein wenig.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Hier kommt ein Load Balancer zum Verteilen des Datenverkehrs zwischen zwei Webservern, ein Cache zwischen dem Webdienst und der Geschäftslogik und ein weiterer Cache zwischen der Geschäftslogik und der Datenbank zum Einsatz. Dies ist genau die Architektur, die Bell Mitte der 2000er Jahre für seine Lastverteilungs- und Blau/Grün-Bereitstellungsanwendung verwendete. Bis vor einiger Zeit funktionierte alles gut, da dieses Schema für eine monolithische Struktur gedacht war.

Das folgende Bild zeigt, wie MS empfiehlt, von einem Monolithen zu Microservices überzugehen – einfach jeden der Hauptdienste in separate Microservices aufzuteilen. Bei der Umsetzung dieses Plans machte Bell einen Fehler.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Sie teilten alle ihre Dienste in verschiedene Ebenen ein, die jeweils aus vielen einzelnen Diensten bestanden. Der Webdienst umfasste beispielsweise Microservices für die Darstellung und Authentifizierung von Inhalten, der Geschäftslogikdienst bestand aus Microservices für die Verarbeitung von Bestellungen und Kontoinformationen und die Datenbank war in eine Reihe von Microservices mit speziellen Daten unterteilt. Sowohl das Web als auch die Geschäftslogik und die Datenbank waren zustandslose Dienste.

Dieses Bild war jedoch völlig falsch, da es keine Geschäftsbereiche außerhalb des IT-Clusters des Unternehmens abbildete. Dieses Schema berücksichtigte keine Verbindung mit der Außenwelt, sodass nicht klar war, wie man beispielsweise Geschäftsanalysen von Drittanbietern erhalten konnte. Ich stelle fest, dass sie auch mehrere Dienste erfunden haben, nur um die Karrieren einzelner Mitarbeiter zu fördern, die versuchten, so viele Menschen wie möglich zu verwalten, um mehr Geld dafür zu bekommen.

Sie glaubten, dass die Umstellung auf Microservices so einfach sei, wie die Übernahme ihrer internen N-Tier-Physical-Layer-Infrastruktur und die Installation von Docker darauf. Werfen wir einen Blick darauf, wie die traditionelle N-Tier-Architektur aussieht.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Es besteht aus 4 Ebenen: der UI-Benutzeroberflächenebene, der Geschäftslogikebene, der Datenzugriffsebene und der Datenbank. Fortschrittlicher ist DDD (Domain-Driven Design) oder softwareorientierte Architektur, bei der die beiden mittleren Ebenen Domänenobjekte und ein Repository sind.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Ich habe versucht, verschiedene Veränderungsbereiche und Verantwortungsbereiche in dieser Architektur zu betrachten. In einer typischen N-Tier-Anwendung werden verschiedene Änderungsbereiche klassifiziert, die die Struktur vertikal von oben nach unten durchdringen. Dabei handelt es sich um Kataloge, auf einzelnen Computern durchgeführte Konfigurationseinstellungen und Checkout-Prüfungen, die von meinem Team durchgeführt wurden.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Die Besonderheit dieses Schemas besteht darin, dass die Grenzen dieser Änderungsbereiche nicht nur die Ebene der Geschäftslogik betreffen, sondern sich auch auf die Datenbank erstrecken.

Schauen wir uns an, was es bedeutet, ein Dienst zu sein. Es gibt 6 charakteristische Eigenschaften einer Servicedefinition – es handelt sich um Software, die:

  • erstellt und verwendet von einer bestimmten Organisation;
  • ist für den Inhalt, die Verarbeitung und/oder Bereitstellung einer bestimmten Art von Informationen innerhalb des Systems verantwortlich;
  • kann unabhängig erstellt, bereitgestellt und betrieben werden, um spezifische betriebliche Anforderungen zu erfüllen;
  • kommuniziert mit Verbrauchern und anderen Diensten und stellt Informationen auf der Grundlage von Vereinbarungen oder vertraglichen Garantien bereit;
  • schützt sich vor unbefugtem Zugriff und seine Informationen vor Verlust;
  • geht mit Ausfällen so um, dass diese nicht zu Informationsschäden führen.

Alle diese Eigenschaften können in einem Wort „Autonomie“ ausgedrückt werden. Dienste funktionieren unabhängig voneinander, erfüllen bestimmte Einschränkungen und definieren Verträge, auf deren Grundlage Menschen die Informationen erhalten können, die sie benötigen. Konkrete Technologien, deren Einsatz selbstverständlich ist, habe ich nicht erwähnt.

Schauen wir uns nun die Definition von Microservices an:

  • Ein Microservice ist klein und darauf ausgelegt, ein bestimmtes Problem zu lösen.
  • Der Microservice ist autonom;
  • Beim Erstellen einer Microservice-Architektur wird die Stadtplanungsmetapher verwendet. Dies ist die Definition aus Sam Newmans Buch „Building Microservices“.

Die Definition von Bounded Context stammt aus dem Buch Domain-Driven Design von Eric Evans. Dies ist ein Kernmuster in DDD, einem Architekturdesignzentrum, das mit volumetrischen Architekturmodellen arbeitet, diese in verschiedene begrenzte Kontexte unterteilt und die Interaktionen zwischen ihnen explizit definiert.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Einfach ausgedrückt bezeichnet ein begrenzter Kontext den Umfang, in dem ein bestimmtes Modul verwendet werden kann. In diesem Zusammenhang handelt es sich um ein logisch einheitliches Modell, das beispielsweise in Ihrer Geschäftsdomäne zu sehen ist. Wenn Sie das Personal, das an Aufträgen beteiligt ist, fragen, wer ein Kunde ist, erhalten Sie eine Definition, wenn Sie die Vertriebsmitarbeiter fragen, erhalten Sie eine andere, und die Darsteller geben Ihnen eine dritte Definition.

Bounded Context sagt also: Wenn wir keine klare Definition dessen geben können, was ein Verbraucher unserer Dienste ist, definieren wir die Grenzen, innerhalb derer wir über die Bedeutung dieses Begriffs sprechen können, und definieren wir dann die Übergangspunkte zwischen diesen verschiedenen Definitionen. Das heißt, wenn wir aus der Sicht der Auftragserteilung über einen Kunden sprechen, bedeutet dies dies und das, und wenn wir aus der Sicht des Vertriebs dies und das meinen.

Die nächste Definition eines Microservices ist die Kapselung jeglicher Art von internen Vorgängen, um das „Durchsickern“ der Komponenten des Arbeitsprozesses in die Umgebung zu verhindern. Als nächstes kommt die „Definition expliziter Verträge für externe Interaktionen oder externe Kommunikation“, die durch die Idee von Verträgen repräsentiert wird, die von SLAs ausgehen. Die letzte Definition ist die Metapher einer Zelle oder Zelle, was die vollständige Kapselung einer Reihe von Operationen innerhalb eines Mikrodienstes und das Vorhandensein von Rezeptoren für die Kommunikation mit der Außenwelt darin bedeutet.

NDC London-Konferenz. Microservice-Katastrophe verhindern. Teil 1

Also sagten wir zu den Leuten von Bell Computers: „Wir können das Chaos, das Sie verursacht haben, nicht beheben, weil Sie einfach nicht das Geld dafür haben, aber wir werden nur einen Dienst reparieren, um alles in Ordnung zu bringen.“ Sinn." An dieser Stelle erzähle ich Ihnen zunächst, wie wir unseren einzigen Dienst so angepasst haben, dass er auf Anfragen schneller als 9 Minuten reagiert.

22:30 min

Demnächst geht es weiter...

Ein bisschen Werbung

Vielen Dank, dass Sie bei uns geblieben sind. Gefallen Ihnen unsere Artikel? Möchten Sie weitere interessante Inhalte sehen? Unterstützen Sie uns, indem Sie eine Bestellung aufgeben oder an Freunde weiterempfehlen. Cloud-VPS für Entwickler ab 4.99 $, ein einzigartiges Analogon von Einstiegsservern, das von uns für Sie erfunden wurde: Die ganze Wahrheit über VPS (KVM) E5-2697 v3 (6 Kerne) 10 GB DDR4 480 GB SSD 1 Gbit/s ab 19 $ oder wie teilt man sich einen Server? (verfügbar mit RAID1 und RAID10, bis zu 24 Kerne und bis zu 40 GB DDR4).

Dell R730xd 2-mal günstiger im Equinix Tier IV-Rechenzentrum in Amsterdam? Nur hier 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6 GHz 14C 64 GB DDR4 4 x 960 GB SSD 1 Gbit/s 100 TV ab 199 $ in den Niederlanden! Dell R420 – 2x E5-2430 2.2 GHz 6C 128 GB DDR3 2 x 960 GB SSD 1 Gbit/s 100 TB – ab 99 $! Lesen über Wie baut man ein Infrastrukturunternehmen auf? Klasse mit dem Einsatz von Dell R730xd E5-2650 v4 Servern im Wert von 9000 Euro für einen Cent?

Source: habr.com

Kommentar hinzufügen