BLOG | NGINX

Einführung von Microservices bei Netflix: Lektionen für die architektonische Gestaltung

NGINX-Teil-von-F5-horiz-schwarz-Typ-RGB
Tony Mauro Miniaturbild
Tony Mauro
Veröffentlicht am 19. Februar 2015

In einigen aktuellen Blogbeiträgen haben wir erläutert, warum wir die Einführung einer vierstufigen Anwendungsarchitektur für entscheidend halten, in der Anwendungen als Microservices- Sätze entwickelt und bereitgestellt werden. Es wird immer deutlicher, dass man mit der Verwendung von Entwicklungsprozessen und Anwendungsarchitekturen, die vor zehn Jahren einwandfrei funktioniert haben, einfach nicht schnell genug reagieren kann, um das Interesse mobiler Benutzer zu wecken und aufrechtzuerhalten, denen eine ständig wachsende Zahl von Apps zur Verfügung steht.

Die Umstellung auf eine Microservices-Architektur eröffnet Unternehmen spannende Marktchancen. Für Systemarchitekten und Entwickler verspricht es ein beispielloses Maß an Kontrolle und Geschwindigkeit bei der Bereitstellung innovativer neuer Web-Erlebnisse für Kunden. Doch bei diesem atemberaubenden Tempo kann es einem vorkommen, als gäbe es nicht viel Spielraum für Fehler. In der realen Welt können Sie die Entwicklung und Bereitstellung Ihrer Apps nicht unterbrechen, während Sie die Prozesse dafür umrüsten. Sie wissen, dass Ihr zukünftiger Erfolg von der Umstellung auf eine Microservices-Architektur abhängt, aber wie setzen Sie diese konkret um?

Zum Glück für uns gibt es inzwischen mehrere Early Adopter von Microservices , die ihr Fachwissen im Sinne von Open Source großzügig weitergeben, und zwar nicht nur in Form von veröffentlichtem Code, sondern auch in Konferenzpräsentationen und Blogbeiträgen. Netflix ist ein führendes Beispiel. Als Director of Web Engineering und später als Cloud Architect überwachte Adrian Cockcroft den Übergang des Unternehmens von einem traditionellen Entwicklungsmodell mit 100 Ingenieuren, die eine monolithische DVD-Verleihanwendung erstellten, zu einer Microservices-Architektur mit vielen kleinen Teams, die für die End-to-End-Entwicklung Hunderter Microservices verantwortlich waren, die zusammenarbeiten, um täglich digitale Unterhaltung an Millionen von Netflix-Kunden zu streamen. Cockcroft ist heute Technology Fellow bei Battery Ventures und ein bekannter Verfechter der Microservices- und Cloud-native-Architekturen. Außerdem ist er Mitglied des Technical Advisory Board von NGINX.

In einer zweiteiligen Blogbeitragsserie präsentieren wir die wichtigsten Erkenntnisse aus zwei Vorträgen, die Cockcroft letztes Jahr gehalten hat, und zwar auf der ersten jährlichen NGINX-Konferenz im Oktober und bei einem Silicon Valley Microservices Meetup einige Monate zuvor. (Auch die kompletten Videoaufzeichnungen sind sehenswert.)

Was ist eine Microservices-Architektur?

Cockcroft definiert eine Microservices-Architektur als eine serviceorientierte Architektur, die aus lose gekoppelten Elementen mit begrenzten Kontexten besteht .

Lose gekoppelt bedeutet, dass Sie die Dienste unabhängig voneinander aktualisieren können; für die Aktualisierung eines Dienstes ist keine Änderung anderer Dienste erforderlich. Wenn Sie über eine Reihe kleiner, spezialisierter Dienste verfügen, diese aber dennoch gemeinsam aktualisieren müssen, handelt es sich dabei nicht um Mikrodienste, da sie nicht lose gekoppelt sind. Eine Art der Kopplung, die bei der Umstellung auf eine Microservices-Architektur oft übersehen wird, ist die Datenbankkopplung, bei der alle Dienste mit derselben Datenbank kommunizieren und die Aktualisierung eines Dienstes eine Änderung des Schemas bedeutet. Sie müssen die Datenbank aufteilen und denormalisieren.

Das Konzept der begrenzten Kontexte stammt aus dem Buch „Domain Driven Design“ von Eric Evans. Ein Microservice mit korrekt begrenztem Kontext ist für die Zwecke der Softwareentwicklung in sich geschlossen. Sie können den Code des Microservice verstehen und aktualisieren, ohne etwas über die internen Vorgänge seiner Peers zu wissen, da der Microservice und seine Peers ausschließlich über APIs interagieren und daher keine Datenstrukturen, Datenbankschemata oder andere interne Darstellungen von Objekten teilen.

Wenn Sie Anwendungen für das Internet entwickelt haben, sind Sie mit diesen Konzepten bereits vertraut, wenn auch nicht dem Namen nach, dann doch aus der Praxis. Die meisten mobilen Apps kommunizieren mit einer ganzen Reihe von Backend-Diensten, damit ihre Benutzer Dinge wie das Teilen auf Facebook, das Abrufen von Wegbeschreibungen von Google Maps und das Suchen von Restaurants auf Foursquare tun können – und das alles im Kontext der App. Wenn Ihre mobile App eng mit diesen Diensten verknüpft wäre, müssten Sie vor der Veröffentlichung eines Updates mit allen Entwicklungsteams sprechen, um sicherzustellen, dass Ihre Änderungen nichts beschädigen.

Wenn Sie mit einer Microservices-Architektur arbeiten, denken Sie an andere interne Entwicklungsteams wie diese Internet-Backends: als externe Dienste, mit denen Ihr Microservice über APIs interagiert. Der allgemein verstandene „Vertrag“ zwischen Microservices besteht darin, dass ihre APIs stabil und vorwärtskompatibel sind. Genauso wie es nicht akzeptabel ist, dass sich die Google Maps API ohne Vorwarnung und auf eine Art und Weise ändert, die den Benutzern Probleme bereitet, kann sich Ihre API zwar weiterentwickeln, muss aber mit früheren Versionen kompatibel bleiben.

Best Practices für den Entwurf einer Microservices-Architektur

Cockcroft beschreibt seine Rolle als Cloud-Architekt bei Netflix nicht im Hinblick auf die Kontrolle der Architektur, sondern als das Entdecken und Formalisieren der Architektur, die sich beim Aufbau durch die Netflix-Ingenieure herausbildete. Das Netflix-Entwicklungsteam hat mehrere Best Practices für den Entwurf und die Implementierung einer Microservices-Architektur etabliert.

Erstellen Sie für jeden Microservice einen separaten Datenspeicher

Verwenden Sie nicht denselben Back-End-Datenspeicher für mehrere Microservices. Sie möchten, dass das Team für jeden Microservice die Datenbank auswählt, die am besten zum Service passt. Darüber hinaus ist es mit einem einzigen Datenspeicher zu einfach für von verschiedenen Teams geschriebene Microservices, Datenbankstrukturen gemeinsam zu nutzen, möglicherweise unter dem Vorwand, Doppelarbeit zu vermeiden. Wenn also ein Team die Datenbankstruktur aktualisiert, müssen auch andere Dienste, die diese Struktur verwenden, geändert werden.

Durch die Aufteilung der Daten kann die Datenverwaltung komplizierter werden, da die einzelnen Speichersysteme leichter ihre Synchronisierung verlieren oder inkonsistent werden können und sich Fremdschlüssel unerwartet ändern können. Sie müssen ein Tool hinzufügen, das die Stammdatenverwaltung (MDM) durchführt, indem es im Hintergrund arbeitet, um Inkonsistenzen zu finden und zu beheben. Beispielsweise könnte es alle Datenbanken untersuchen, in denen Teilnehmer-IDs gespeichert sind, um sicherzustellen, dass in allen die gleichen IDs vorhanden sind (d. h. in keiner Datenbank fehlen oder es sind zusätzliche IDs vorhanden). Sie können Ihr eigenes Tool schreiben oder eines kaufen. Viele kommerzielle relationale Datenbankverwaltungssysteme (RDBMSs) führen derartige Prüfungen durch, stellen jedoch in der Regel zu viele Anforderungen an die Kopplung und sind daher nicht skalierbar.

Halten Sie den Code auf einem ähnlichen Reifegrad

Halten Sie den gesamten Code in einem Microservice auf einem ähnlichen Reife- und Stabilitätsniveau. Mit anderen Worten: Wenn Sie Code in einem bereits gut funktionierenden bereitgestellten Microservice hinzufügen oder neu schreiben müssen, besteht die beste Vorgehensweise normalerweise darin, einen neuen Microservice für den neuen oder geänderten Code zu erstellen und den vorhandenen Microservice beizubehalten. [Editor – Dies wird manchmal als Prinzip der unveränderlichen Infrastruktur bezeichnet.] Auf diese Weise können Sie den neuen Code iterativ bereitstellen und testen, bis er fehlerfrei und maximal effizient ist, ohne dass Sie beim vorhandenen Microservice Fehler oder Leistungseinbußen riskieren. Sobald der neue Microservice so stabil ist wie das Original, können Sie die beiden wieder zusammenführen, sofern sie tatsächlich gemeinsam eine einzige Funktion erfüllen oder sich aus ihrer Kombination andere Effizienzvorteile ergeben. Allerdings kommt es nach Cockcrofts Erfahrung viel häufiger vor, dass man zu dem Schluss kommt, dass man einen Microservice aufteilen sollte, weil er zu groß geworden ist.

Erstellen Sie für jeden Microservice einen separaten Build

Führen Sie für jeden Microservice einen separaten Build durch, damit dieser Komponentendateien aus dem Repository in den für ihn geeigneten Revisionsebenen abrufen kann. Dies führt manchmal dazu, dass verschiedene Microservices einen ähnlichen Satz von Dateien, jedoch auf unterschiedlichen Revisionsebenen, abrufen. Dadurch wird es möglicherweise schwieriger, Ihren Code durch Außerbetriebnahme alter Dateiversionen zu bereinigen (da Sie genauer prüfen müssen, ob eine Revision nicht mehr verwendet wird). Im Hinblick auf die Benutzerfreundlichkeit beim Erstellen neuer Microservices ist dies jedoch ein akzeptabler Kompromiss. Die Asymmetrie ist beabsichtigt: Sie möchten, dass die Einführung eines neuen Mikrodienstes, einer neuen Datei oder einer neuen Funktion einfach und nicht gefährlich ist.

Bereitstellung in Containern

Das Bereitstellen von Microservices in Containern ist wichtig, da Sie für die Bereitstellung aller Komponenten nur ein einziges Tool benötigen. Solange sich der Microservice in einem Container befindet, weiß das Tool, wie es ihn bereitstellt. Dabei ist es egal, um welchen Behälter es sich handelt. Dennoch scheint sich Docker sehr schnell zum De-facto-Standard für Container entwickelt zu haben.

Server als zustandslos behandeln

Behandeln Sie Server, insbesondere solche, auf denen kundenorientierter Code ausgeführt wird, als austauschbare Mitglieder einer Gruppe. Sie erfüllen alle die gleiche Funktion, Sie müssen sich also nicht um jeden einzelnen kümmern. Ihre einzige Sorge besteht darin, dass genügend davon vorhanden sind, um die von Ihnen benötigte Arbeitsmenge zu bewältigen. Mithilfe der automatischen Skalierung können Sie die Zahlen nach oben und unten anpassen. Funktioniert eines nicht mehr, wird es automatisch durch ein anderes ersetzt. Vermeiden Sie „Snowflake“-Systeme, bei denen Sie für die Ausführung spezieller Funktionen auf einzelne Server angewiesen sind.

Cockcrofts Analogie besteht darin, dass man sich Server wie Vieh und nicht wie Haustiere vorstellen sollte. Wenn Sie in der Produktion eine Maschine haben, die eine spezielle Funktion erfüllt, Sie deren Namen kennen und alle traurig sind, wenn sie ausfällt, dann ist sie ein Haustier. Stattdessen sollten Sie sich Ihre Server wie eine Herde Kühe vorstellen. Entscheidend ist, wie viele Gallonen Milch Sie bekommen. Wenn Sie eines Tages feststellen, dass Sie weniger Milch als üblich bekommen, finden Sie heraus, welche Kühe nicht gut produzieren und ersetzen Sie diese.

Die Bereitstellungsarchitektur von Netflix basiert auf NGINX

Netflix ist ein langjähriger Benutzer von NGINX Open Source und wurde nach der Firmengründung im Jahr 2011 der erste Kunde von NGINX, Inc. Tatsächlich hat Netflix NGINX als Herzstück seiner Bereitstellungsinfrastruktur gewählt , Open Connect , eines der größten Content Delivery Networks (CDNs) der Welt. Mit der Fähigkeit, Tausende und manchmal Millionen von Anfragen pro Sekunde zu verarbeiten, sind NGINX und NGINX Plus optimale Lösungen für eine leistungsstarke HTTP-Zustellung und ermöglichen es Unternehmen wie Netflix, Millionen von Kunden täglich hochwertige digitale Erlebnisse zu bieten.

Videoaufnahmen

Schnelle Lieferung
nginx.conf 2014, Oktober 2014

Migration zu Microservices, Teil 1
Silicon Valley Microservices Meetup, August 2014

Migration zu Microservices, Teil 2
Silicon Valley Microservices Meetup, August 2014


„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."