Die Übersetzung des Artikels wurde speziell für Studierende des Kurses „High Load Architect“ erstellt .

Einleitung
In der Netflix-Microservice-Architektur kann die Übertragung von Datensätzen von einem zu mehreren Endpunkten äußerst schwierig sein. Diese Datensätze können alles von einer Servicekonfiguration bis hin zu Batch-Verarbeitungsergebnissen enthalten. Um den Zugriff zu optimieren, ist häufig eine residente Datenbank erforderlich, und Änderungen müssen sofort nach der Aktualisierung der Daten gesendet werden.
Ein Beispiel, das die Notwendigkeit einer verteilten Verteilung eines Datensatzes widerspiegelt, sieht folgendermaßen aus: Netflix führt zu einem bestimmten Zeitpunkt eine große Anzahl von A / B-Tests durch. Diese Tests decken mehrere Dienste und Befehle ab, und die Testbetreiber sollten in der Lage sein, sich im laufenden Betrieb neu zu konfigurieren. Es erfordert auch die Fähigkeit, Knoten zu erkennen, die nicht die neueste Testkonfiguration erhalten konnten, und die Fähigkeit, ein Rollback auf ältere Versionen durchzuführen, falls etwas schief geht.
Ein weiteres Beispiel für einen Datensatz, der verteilt werden muss, ist die Ausgabesequenz eines maschinellen Lernmodells: Die Ergebnisse seiner Arbeit können von mehreren Teams verwendet werden. ML-Teams sind jedoch nicht unbedingt daran interessiert, ununterbrochene Zugriffsdienste im Notfall zu unterstützen. Anstelle der Situation, in der jedes Team Backups erstellen muss, um ein kurzes Rollback durchführen zu können, wird besonderes Augenmerk darauf gelegt, dass mehrere Teams die Ergebnisse eines einzigen Teams verwenden können.
Ohne Unterstützung auf Infrastrukturebene versucht jedes Team letztendlich, seine eigene Lösung zu implementieren, aber es kommt zu unterschiedlichen Teams mit unterschiedlichem Erfolg. Die Datensätze selbst sind unterschiedlich groß, von einigen Bytes bis zu einigen Gigabytes. Es ist wichtig, die Fähigkeit zu schaffen, die Leistung von Prozessen zu überwachen und Fehlfunktionen mit speziellen Tools zu erkennen, damit Bediener schnell Änderungen vornehmen können, ohne ihre eigene Lösung erstellen zu müssen.
DatenverbreitungBei Netflix verwenden wir ein internes Pub / Sub-Datensystem namens Gutenberg. Mit Gutenberg können Sie Datensätze mit Versionsverwaltung verteilen. Empfänger abonnieren die Daten und erhalten ihre neuesten Versionen, wenn sie veröffentlicht werden. Jede Version des Datensatzes bleibt unverändert und enthält eine vollständige Darstellung der Daten, dh es besteht keine Abhängigkeit von früheren Versionen. Mit Gutenberg können Sie alte Versionen von Daten anzeigen, falls Sie beispielsweise ein Debugging, eine schnelle Lösung eines Datenproblems oder eine Umschulung eines maschinellen Lernmodells benötigen. In diesem Artikel werden wir über die Architektur auf hoher Ebene von Gutenberg sprechen.
Datenmodell
1 Thema -> viele VersionenGutenbergs Top-Design ist das Thema. Der Herausgeber veröffentlicht Daten innerhalb des Themas und die Empfänger extrahieren sie daraus. Die Veröffentlichung im Thema wird als separate Version hinzugefügt. Diese zeichnen sich durch eine spezifische Speicherrichtlinie aus, die die Anzahl der Versionen abhängig vom Anwendungsfall bestimmt. Beispielsweise können Sie ein Design so konfigurieren, dass 10 Versionen oder Versionen der letzten 10 Tage gespeichert werden.
Jede Version enthält Metadaten (Schlüssel und Werte) und einen Datenzeiger. Der Datenzeiger kann als spezielle Metadaten betrachtet werden, die angeben, wo die veröffentlichten Daten tatsächlich gespeichert sind. Heute unterstützt Gutenberg direkte Datenzeiger (wenn die Nutzdaten in den Wert des Datenzeigers selbst geschrieben sind) und S3-Datenzeiger (wenn die Nutzdaten in S3 gespeichert sind). Direkte Datenzeiger werden normalerweise verwendet, wenn die Datenmenge gering ist (weniger als 1 MB), und S3 wird als Sicherungsspeicher verwendet, wenn das Datenvolumen groß ist.
1 Thema -> viele veröffentlichte SetsGutenberg bietet die Möglichkeit, eine Veröffentlichung an eine bestimmte Gruppe von Empfängerbenutzern zu senden. Beispielsweise kann eine Gruppe nach einer bestimmten Region, Anwendung oder einem bestimmten Cluster gruppiert werden. Dies kann verwendet werden, um die Qualität von Datenänderungen zu steuern oder den Datensatz zu begrenzen, sodass eine Teilmenge von Anwendungen ihn abonnieren kann. Publisher bestimmen den Veröffentlichungsbereich einer bestimmten Version der Daten und können Bereiche zu zuvor veröffentlichten Daten hinzufügen. Beachten Sie, dass dies bedeutet, dass das Konzept der neuesten Version der Daten von einem bestimmten Bereich abhängt. Je nach dem vom Herausgeber festgelegten Veröffentlichungsbereich erhalten die beiden Anwendungen möglicherweise die neuesten unterschiedlichen Versionen der Daten. Der Gutenberg-Dienst ordnet Empfängeranwendungen Veröffentlichungsbereichen zu, bevor entschieden wird, was als neueste Version gesendet werden soll.
Anwendungsfälle
Der häufigste Anwendungsfall für Gutenberg ist die Verteilung von Daten unterschiedlicher Größe von einem Verlag an mehrere Empfänger. Häufig werden die Daten im Speicher des Empfängers gespeichert und als "gemeinsamer Cache" verwendet, in dem sie während der Ausführung des Empfängercodes immer verfügbar bleiben und bei Bedarf atomar unter der Haube ausgetauscht werden. Viele dieser Anwendungsfälle können in „Konfigurationen“ gruppiert werden, z. B. die
Open Connect Appliance- Cache-Konfiguration, unterstützte Gerätetyp-IDs, unterstützte Zahlungsmethoden-Metadaten und A / B-Testkonfigurationen. Gutenberg bietet eine Abstraktion zwischen dem Veröffentlichen und Empfangen dieser Daten, sodass Verlage ihre Anwendung frei durchlaufen können, ohne die nachgeschalteten Empfänger zu beeinträchtigen. In einigen Fällen erfolgt die Veröffentlichung über eine von Gutenberg verwaltete Benutzeroberfläche, und die Teams müssen ihre eigene Veröffentlichungsanwendung überhaupt nicht berühren.
Eine weitere Verwendung des Gutenberg-Systems ist die Speicherung versionierter Daten. Dies ist nützlich für Anwendungen für maschinelles Lernen, bei denen Teams Modelle auf der Grundlage von Verlaufsdaten erstellen und trainieren, deren zeitliche Veränderung beobachten, dann bestimmte Parameter ändern und die Anwendung erneut ausführen. Am häufigsten wird Gutenberg bei Stapelberechnungen verwendet, um die Ergebnisse dieser Berechnungen als verschiedene Versionen von Datensätzen zu speichern und zu verteilen. In Online-Anwendungsfällen werden Themen abonniert, um Echtzeitdaten aus den neuesten Versionssätzen bereitzustellen, während autonome Systeme Verlaufsdaten aus denselben Themen verwenden können, um beispielsweise ein Modell für maschinelles Lernen zu vermitteln.
Es ist wichtig zu beachten, dass Gutenberg nicht als Ereignissystem konzipiert ist, sondern ausschließlich zur Versionskontrolle und Datenverteilung dient. Insbesondere bedeuten häufige Veröffentlichungen nicht, dass der Abonnent jede Version erhalten muss. Wenn er ein Update anfordert, erhält er die neueste Version, auch wenn seine aktuelle Version derzeit weit hinter der aktuellen Version zurückliegt. Herkömmliche Pub-Sub- oder Ereignissysteme eignen sich eher für kleine Nachrichten, die nacheinander gesendet werden. Das heißt, Empfänger können eine Idee für den gesamten Datensatz erstellen, indem sie den gesamten (komprimierten) Ereignisstrom verwenden. Gutenberg beabsichtigt jedoch, eine vollständige, unveränderliche Darstellung eines Datensatzes zu veröffentlichen und zu verwenden.
Entwicklung und Architektur
Gutenberg besteht aus einem gRPC-Service und einer REST-API sowie einer Java-Client-Bibliothek, die die gRPC-API verwendet.
Hochwertige ArchitekturKunde
Die Gutenberg-Clientbibliothek verarbeitet Aufgaben wie das Verwalten eines Abonnements, das Laden / Entladen von S3,
Atlas- Metriken und Parameter, die mithilfe der
Archaius- Eigenschaften konfiguriert werden können. Sie interagiert mit dem Gutenberg-Service über gRPC und nutzt
Eureka , um Services zu ermitteln.
Posten
Verleger verwenden in der Regel APIs auf hoher Ebene, um Zeichenfolgen, Dateien und Bytearrays zu veröffentlichen. Abhängig von der Größe der Daten können sie als direkter Zeiger auf die Daten veröffentlicht oder in S3 hochgeladen und dann als Datenzeiger S3 veröffentlicht werden. Der Client kann die Nutzdaten im Namen des Publishers auf S3 hochladen oder nur die in S3 bereits vorhandenen Nutzdaten-Metadaten veröffentlichen.
Direkte Datenzeiger werden automatisch global repliziert. In S3 veröffentlichte Daten werden standardmäßig vom Herausgeber in mehreren Bereichen hochgeladen, können jedoch auch angepasst werden.
Abonnementverwaltung
Die Clientbibliothek bietet die Verwaltung von Empfängerabonnements. Auf diese Weise können Benutzer Abonnements für bestimmte Themen erstellen, aus denen die Bibliothek Daten extrahiert (z. B. aus S3), um diese an den vom Benutzer festgelegten Empfänger zu übertragen. Abonnements funktionieren nach dem Umfragemodell. Sie fordern alle 30 Sekunden ein neues Update vom Service an und senden die Version, die sie zuletzt erhalten haben. Abonnierte Kunden verwenden keine ältere Version der Daten als die, über die sie derzeit verfügen, wenn sie nicht behoben sind (siehe "Fehlertoleranz" weiter unten). Die Logik für wiederholte Anforderungen ist verkabelt und konfigurierbar. Beispielsweise können Benutzer Gutenberg so konfigurieren, dass ältere Versionen der Daten verwendet werden, wenn der Downloadvorgang unterbrochen wird, oder dass die neueste Version der Daten beim Start verarbeitet wird, meistens, um mit Datenänderungen zu arbeiten, die nicht mit Feedback kompatibel sind. Gutenberg bietet auch ein vorkonfiguriertes Abonnement an, in dem die neuesten Daten gespeichert und automatisch aktualisiert werden, wenn Änderungen eintreffen. Dies trifft auf die meisten Abonnement-Anwendungsfälle zu, in denen Abonnenten zu einem bestimmten Zeitpunkt nur den aktuellen Wert berücksichtigen, sodass Benutzer einen Standardwert angeben können, z. B. für ein Thema, das noch nie zuvor veröffentlicht wurde (z. B. wenn das Thema für die Konfiguration verwendet wird), oder Wenn je nach Thema ein Fehler auftritt (um zu vermeiden, dass der Start des Dienstes blockiert wird, wenn ein gültiger Standardwert vorliegt).
Empfänger-API
Gutenberg stellt auch Client-APIs auf hoher Ebene bereit, die unter der Haube über gRPC-APIs auf niedriger Ebene verfügen und zusätzliche Funktionen und Transparenz bei der Ausführung von Abfragen bieten. Ein Beispiel ist das Herunterladen von Daten für ein bestimmtes Thema und eine bestimmte Version, die häufig von mit
Netflix Hollow verbundenen Komponenten verwendet werden. Ein weiteres Beispiel ist der Empfang der neuesten Version eines Themas zu einem bestimmten Zeitpunkt - ein gängiger Anwendungsfall zum Debuggen oder Lehren von Modellen für maschinelles Lernen.
Nachhaltigkeit und "Transparenz" des Kunden
Gutenberg wurde mit dem Ziel entwickelt, den Empfängerservices einen erfolgreichen Start zu ermöglichen, anstatt zu gewährleisten, dass sie mit den aktuellsten Daten beginnen. Aus diesem Grund wurde die Clientbibliothek mit Sicherungslogik erstellt, um Zustände zu verarbeiten, bei denen keine Interaktion mit dem Gutenberg-Dienst möglich ist. Wenn die HTTP-Anforderungen fehlschlagen, lädt der Client den Backup-Metadaten-Cache des veröffentlichten Themas aus S3 und arbeitet damit. Dieser Cache enthält alle Informationen, um zu entscheiden, ob das Update angewendet werden soll und wo die Daten abgerufen werden sollen (entweder aus den Publikationsmetadaten selbst oder aus S3). Auf diese Weise können Kunden Daten abrufen (die abhängig vom aktuellen Status des Sicherungscaches möglicherweise veraltet sind), ohne den Dienst zu verwenden.
Einer der Vorteile der Bereitstellung einer Clientbibliothek besteht in der Möglichkeit, Metriken abzurufen, mit denen Infrastrukturprobleme im Allgemeinen und Fehler in bestimmten Anwendungen gemeldet werden können. Heute werden diese Metriken vom Gutenberg-Team verwendet, um die SLI-Verteilung von Veröffentlichungen und Warnungen bei typischen Problemen zu überwachen. Einige Kunden verwenden diese Metriken auch, um bestimmte anwendungsspezifische Fehler zu melden, z. B. einzelne Veröffentlichungsfehler oder eine bestimmte Themenverweigerung.
Server
Gutenberg ist eine
Governator / Tomcat-Anwendung, die gRPC- und REST-Endpunkte bereitstellt. Es verwendet den global replizierten Cassandra-Cluster zum Speichern und Verteilen von Publikationsmetadaten in jeder Region. Instanzen, die Empfängeranforderungen verarbeiten, werden getrennt von Instanzen skaliert, die Veröffentlichungsanforderungen verarbeiten. Es gibt ungefähr 1.000 Mal mehr Publikationsanfragen als Publikationsanfragen. Darüber hinaus können Sie auf diese Weise die Abhängigkeit der Veröffentlichung vom Eingang beseitigen, sodass ein plötzlicher Anstieg der Veröffentlichungen sich nicht auf den Eingang auswirkt und umgekehrt.
Jede Instanz im Empfängeranforderungscluster verarbeitet ihren eigenen speicherinternen Cache der letzten Veröffentlichungen und ruft ihn alle paar Sekunden von Cassandra ab. Dies ist erforderlich, um eine große Anzahl von Empfangsanforderungen von signierten Clients zu verarbeiten, ohne Datenverkehr an den Cassandra-Cluster zu übertragen. Darüber hinaus schützen Caches mit einem kleinen TTL-Anforderungspool vor Abfragespitzen, die Cassandra möglicherweise so stark verlangsamen, dass sie die gesamte Region betreffen. Wir hatten Situationen, in denen plötzliche Fehler, die mit der Umverteilung großer Cluster zusammenfielen, zu Unterbrechungen im Gutenberg-Dienst führten. Darüber hinaus verwenden wir den adaptiven
Parallelitätsbegrenzer der ursprünglichen Anwendung, um Anwendungen mit falschem Verhalten zu unterdrücken, ohne andere zu beeinflussen.
In Fällen, in denen Daten in S3 in mehreren Regionen veröffentlicht werden, entscheidet der Server, welches Segment zum Herunterladen an den Client zurückgesendet wird, je nachdem, wo sich der Client befindet. Außerdem kann der Dienst dem Client ein Segment in der nächstgelegenen Region bereitstellen oder den Client zwingen, in eine andere Region zu wechseln, wenn die aktuelle Region aus dem einen oder anderen Grund getrennt wird.
Bevor Gutenberg die Abonnementdaten an die Empfänger zurücksendet, überprüft es zunächst die Daten auf Konsistenz. Wenn die Überprüfung fehlschlägt und der Abonnent bereits einige Daten erhalten hat, gibt der Dienst nichts zurück, was bedeutet, dass das Update nicht verfügbar ist. Wenn der Abonnenten-Client noch keine Daten erhalten hat (dies bedeutet normalerweise, dass er gerade gestartet wurde), fordert der Dienst den Verlauf des Themas an und gibt den letzten Wert zurück, der die Konsistenzprüfung besteht. Dies ist auf die Tatsache zurückzuführen, dass es auf Cassandra-Ebene zu episodischen Replikationsverzögerungen kommt, bei denen die Metadaten der zuletzt veröffentlichten Version nur teilweise repliziert wurden, bis Abonnenten neue Daten anfordern. Dies kann dazu führen, dass der Client unvollständige Daten empfängt, was dann zu Datenanforderungsfehlern oder Fehlern in der Geschäftslogik führt. Das Durchführen solcher Konsistenzprüfungen auf dem Server schützt die Empfänger vor Warnungen über mögliche Konsistenz, die mit der Auswahl eines Data Warehouse-Dienstes einhergehen.
Die Möglichkeit, Veröffentlichungen von Themen und Sites zu überwachen, auf denen diese Themen verwendet werden, ist eine wichtige Funktion für die Prüfung und Erfassung von Nutzungsinformationen. Um diese Daten zu erfassen, fängt der Dienst Anforderungen von Publishern und Empfängern ab (sowohl Anforderungen zum Aktualisieren von Daten von Abonnenten als auch von anderen) und indiziert sie mithilfe der
Keystone- Daten-
Pipeline in Elasticsearch. So haben wir die Möglichkeit, Daten für die Überwachung von Themen zu erhalten, die verwendet werden und nicht mehr vorhanden sind. Wir veröffentlichen ausführliche Links zum Kibana-Dashboard über die interne Benutzeroberfläche, damit Themenbesitzer ihre Abonnenten unabhängig verwalten können.
Neben Clustern, die Herausgeber- und Empfängeranforderungen verarbeiten, startet der Gutenberg-Dienst einen weiteren Cluster, der periodische Anforderungen verarbeitet. Insbesondere löst er zwei Probleme:
- Alle paar Minuten werden die neuesten Veröffentlichungen und Metadaten gesammelt und an S3 gesendet. Dies initiiert den Start des Sicherungscaches, der vom Client wie oben beschrieben verwendet wird.
- Der Garbage Collector löscht Versionen von Themen, die ihren Aufbewahrungsrichtlinien nicht entsprechen. Außerdem werden damit verknüpfte Daten (z. B. S3-Objekte) gelöscht, und es wird ein klar definierter Datenlebenszyklus sichergestellt.
Fehlertoleranz
Snap
In der Welt der Anwendungsentwicklung treten erfolglose Bereitstellungen auf, und Rollbacks auf frühere Versionen sind eine gängige Strategie zur Behebung solcher Probleme. Die datengesteuerte Architektur verkompliziert die Situation, da das Verhalten von Daten bestimmt wird, die sich mit der Zeit ändern.
Die von Gutenberg verteilten Daten beeinflussen und steuern in vielen Fällen das Verhalten des Systems. Das heißt, wenn etwas schief geht, müssen Sie einen Rollback auf eine nachgewiesene gute Version der Daten durchführen. Um die Situation zu entschärfen, ermöglicht es Gutenberg, das Thema mit einer bestimmten Version zu "verknüpfen". Die Pins überschreiben die neueste Version der Daten und zwingen den Client, auf diese Version zu aktualisieren. Auf diese Weise können Sie eine kritische Situation schnell beheben, anstatt herauszufinden, wie die neueste Arbeitsversion veröffentlicht werden soll. Sie können sogar eine Bindung auf den Veröffentlichungsbereich anwenden, sodass nur Empfänger aus diesem Bereich die Daten verwenden können. Die Stifte überschreiben auch die Daten, die während der aktiven Bindung veröffentlicht wurden. Wenn der Stift gelöscht wird, erhalten Clients jedoch die neueste Version. Dies kann die neueste angeheftete Version oder eine neue Version sein, die veröffentlicht wurde, während die alte angeheftet wurde.
Sequentielle Bereitstellung
Beim Bereitstellen von neuem Code wird häufig empfohlen, neue Assemblys mit einer Teilmenge des Datenverkehrs zu erstellen, diese schrittweise bereitzustellen oder auf andere Weise das Bereitstellungsrisiko zu verringern und es zu verlangsamen. In Fällen, in denen Daten das Verhalten steuern, sollte ein ähnliches Prinzip angewendet werden.
, Gutenberg, —
Spinnaker . , . , . , , , , , . , AWS- .
Gutenberg Netflix . Gutenberg , 6 . – , 1-2 , 12 .
24- , , . , 200, 7. - , , Hollow. , , , – 60, – 4.
, Gutenberg:
- : Gutenberg Java-, Node.JS Python-. , REST API Gutenberg . , Node.JS Python.
- : Gutenberg . Gutenberg.
- : , . , .
- : , Gutenberg, Gutenberg . , .
- : , , . , Elasticsearch.
- : Netflix – . , Gutenberg , .
Das ist alles. .