Skip to main content

Wie wir die Infrastruktur von Roblox effizienter und widerstandsfähiger gestalten

December 7, 2023

by Daniel Sturman, Chief Technology Officer; Max Ross, Vice President, Engineering; and Michael Wolf, Technical Director


Tech

Mit dem Wachstum von Roblox über die letzten 16 Jahre ist auch die Größe und Komplexität der technischen Infrastruktur, die Millionen von immersiven 3D-Erlebnissen unterstützt, gewachsen. Die Anzahl der Maschinen, die wir unterstützen, hat sich über die letzten zwei Jahre vom 30. Juni 2021 bis heute von ca. 36.000 auf 145.000 verdreifacht. Die Unterstützung der ständig aktiven Erlebnisse für Menschen weltweit erfordert über 1.000 interne Dienste. Um uns dabei zu helfen, die Kosten und Netzwerklatenz unter Kontrolle zu halten, verwenden und verwalten wir diese Maschinen als Teil unserer speziell erstellten und hybriden privaten Cloud-Infrastruktur, die in erster Linie lokal läuft.

Unsere Infrastruktur unterstützt derzeit über 70 Millionen täglich aktive Nutzer:innen weltweit, darunter die Creator:innen, die auf Roblox‘ Wirtschaft für ihre Unternehmen angewiesen sind. Alle diese Millionen von Menschen erwarten einen hohen Grad an Zuverlässigkeit. Durch die immersive Natur dieser Erlebnisse besteht eine extrem niedrige Toleranz für Lags und Latenz, geschweige denn Ausfälle. Roblox ist eine Plattform für Kommunikation und Verbindung, wo Menschen in 3D-Erlebnissen zusammenkommen können. Wenn Leute als ihre Avatare an einem immersiven Ort kommunizieren, sind selbst kleinste Verzögerungen und Fehler bemerkbarer als in Text-Chats oder Konferenzgesprächen.

Im Oktober 2021 erlebten wir einen systemweiten Ausfall. Er begann zunächst in kleinem Ausmaß in einer Komponente in einem Datenzentrum. Er breitete sich jedoch schnell aus, während wir Untersuchungen anstellten, und resultierte letztendlich in einem 73-stündigen Ausfall. Zur selben Zeit teilten wir sowohl Einzelheiten darüber, was passierte, als auch unsere ersten Einsichten über das Problem. Seitdem haben wir diese Einsichten weiterhin untersucht und arbeiten daran, die Widerstandsfähigkeit unserer Infrastruktur gegen diese Art von Fehlern zu erhöhen, die in allen großtechnischen Systemen aufgrund von Faktoren wie extremer Datenverkehrsspitzen, Wetter, Hardware-Fehlern, Software-Fehlern oder auch menschlichen Versagens auftreten. Wenn solche Fehler auftreten, wie können wir sicherstellen, dass sich ein Problem in einer einzigen Komponente oder einer Gruppe von Komponenten nicht über das ganze System erstreckt? Wir haben uns in den letzten zwei Jahren stark mit dieser Frage beschäftigt. Und obwohl die Arbeit daran noch nicht abgeschlossen ist, zahlen sich unsere bisherigen Entwicklungen bereits aus. In den ersten sechs Monaten von 2023, zum Beispiel, sicherten wir 125 Millionen Engagement-Stunden pro Monat im Vergleich zu den ersten sechs Monaten von 2022. Heute teilen wir, was wir bereits unternommen haben, und was unsere langfristige Vision für die Entwicklung eines widerstandsfähigeren Systems ist.

Die Entwicklung eines Schutzmechanismus

Bei großtechnischen Infrastruktursystemen passieren täglich mehrere kleinere Fehler. Wenn bei einer der Maschinen ein Problem auftritt, wodurch sie außer Betrieb genommen werden muss, ist das tragbar, da die meisten Unternehmen mehrere Instanzen ihrer Back-End-Dienste haben. Wenn also eine einzelne Instanz ausfällt, können andere die Workload aufnehmen. Um diese häufigen Fehler zu beheben, werden Anfragen generell automatisch wiederholt, wenn sie eine Fehlernachricht erhalten.

Dies kann sich jedoch Schaden verursachen, wenn ein System oder eine Person zu aggressiv häufige Anfragen schickt, da sich damit diese kleineren Fehler durch die gesamte Infrastruktur oder auf andere Dienste ausbreiten können. Wenn das Netzwerk oder eine Person zu beharrlich ist, kann dies letztendlich jede Instanz dieses Dienstes und potenziell andere Systeme weltweit überlasten. Unser Ausfall im Jahr 2021 was das Resultat von etwas, das recht häufig in großtechnischen Systemen vorkommt: Ein Fehler fängt klein an und breitet sich innerhalb des Systems aus, wobei er so schnell so groß wird, dass es schwierig ist, ihn zu beheben, bevor es zu einem kompletten Ausfall kommt.

Während unseres Ausfalls hatten wir ein aktives Datenzentrum (mit Komponenten darin, die als Backup dienten). Wir brauchten die Fähigkeit, manuell zu einem neuen Datenzentrum zu wechseln, wenn ein Problem das derzeitige zum Stillstand bringt. Unsere oberste Priorität war es, sicherzustellen, dass wir eine Backup-Bereitstellung von Roblox hatten, also haben wir das Backup in einem neuen Datenzentrum in einer anderen geografischen Region errichtet. Dies fügte eine zusätzliche Sicherheitsebene für den Schlimmstfall hinzu: einen Ausfall, der sich durch so viele Komponenten im Datenzentrum ausbreitet, dass es komplett funktionsunfähig wird. Wir haben jetzt ein Datenzentrum, dass Workloads übernimmt (aktiv), und eines, dass auf Standby steht und als Backup dient (passiv). Unser langfristiges Ziel ist es, von dieser Aktiv-Passiv-Konfiguration zu einer Aktiv-Aktiv-Konfiguration zu wechseln, wobei beide Datenzentren die Workloads erledigen und ein Load Balancer die Anfragen zwischen den beiden Zentren anhand von Latenz, Kapazität und Integrität aufteilt. Sobald dies umgesetzt ist, erwarten wir, dass die Zuverlässigkeit überall auf Roblox noch höher wird und eine Umschaltung unverzögert stattfinden kann, statt erst mehrere Stunden nach dem Fehler.

Übergang zu einer Zell-Infrastruktur

Unsere nächste Priorität war die Erschaffung starker Schutzwände innerhalb jedes Datenzentrums, um das Risiko zu verringern, dass ein ganzes Datenzentrum fehlschlägt. Bei Zellen (einige Unternehmen nennen sie auch Cluster), handelt es sich gewissermaßen um eine Reihe von Maschinen, mit denen wir diese Wände erstellen. Wir replizieren Dienste sowohl innerhalb von Zellen als auch zellenübergreifend für zusätzliche Redundanz. Ultimativ möchten wir, dass alle Dienste auf Roblox in Zellen ausgeführt werden, damit sie von starken Schutzwänden und Redundanz profitieren können. Wenn eine Zelle nicht mehr funktionsfähig ist, kann sie sicher abgeschaltet werden. Zellenübergreifende Replikation ermöglicht es dem Dienst, weiterzulaufen, während die betroffene Zelle repariert wird. In einigen Fällen kann die Reparatur der Zelle eine komplette Neuprovisionierung bedeuten. Es ist industrieweit gängig, eine einzelne Maschine oder eine kleine Anzahl an Maschinen neu zu provisionieren, aber dies für eine gesamte Zelle zu tun, die ca. 1.400 Maschinen umfasst, ist es nicht.

Dazu müssen diese Zellen weitestgehend uniform sein, damit wir Workloads schnell und effizient von einer Zelle zur anderen bewegen können. Wir haben einige Voraussetzungen für Dienste, die erfüllt werden müssen, bevor sie in einer Zelle ausgeführt werden können. Zum Beispiel müssen Dienste containerisiert werden, wodurch sie übertragbarer sind und keine Konfigurationsänderungen auf der OS-Ebene vorgenommen werden können. Wir haben eine Infrastruktur-als-Code-Philosophie für Zellen übernommen: Unsere Quellcode-Datenbank enthält die Definition von allem, das in einer Zelle ist, damit wir sie schnell mit Hilfe von automatisierten Tools von Grund auf wiederherstellen können.

Nicht alle Dienste erfüllen derzeit diese Voraussetzungen. Deswegen haben wir daran gearbeitet, den Dienstbesitzer:innen dabei zu helfen, sie so weit wie möglich zu erfüllen, und neue Tools entwickelt, um es einfach zu machen, diese Dienste in Zellen zu migrieren, wenn sie so weit sind. Zum Beispiel „streift“ unser neues Bereitsstellungstool automatisch Dienstbereitstellungen zellenübergreifend, so dass Dienstbesitzer:innen sich keine Gedanken über die Replikationsstrategie machen müssen. Dieses Maß an Präzision macht den Migrationsvorgang sehr herausfordernd und nimmt viel Zeit in Anspruch, aber langfristig wird es sich für das System lohnen:

  • Es ist viel einfacher, einen Fehler zu isolieren und ihn daran zu hindern, sich auf andere Zellen auszubreiten;
  • Unsere Infrastruktur-Engineers können effizienter und schneller arbeiten; und
  • Die Engineers, die Dienste auf der Produktebene entwickeln, welche letztendlich in Zellen bereitgestellt werden, brauchen nicht wissen oder sich darum kümmern, in welchen Zellen ihre Dienste ausgeführt werden.

Größere Herausforderungen lösen

Ähnlich wie Brandschutztüren Flammen in Schach halten, dienen Zellen als starke Schutzwände innerhalb unserer Infrastruktur, um zu helfen, jegliche Probleme, die Fehler in einer einzelnen Zelle auslösen, einzudämmen. Letztendlich werden alle Dienste, die Roblox ausmachen, redundant innerhalb von Zellen und zellenübergreifend bereitgestellt werden. Sobald diese Arbeit abgeschlossen ist, können Probleme zwar immer noch eine gesamte Zelle funktionsunfähig machen, aber es würde extrem schwierig für sie sein, sich außerhalb der Zelle zu verbreiten. Und wenn wir es schaffen, Zellen untereinander auswechselbar zu machen, wird die Wiederherstellung deutlich schneller, da wir zu einer anderen Zelle umschalten können, um das Problem daran zu hindern, Endnutzer:innen zu beeinträchtigen.

Die Herausforderung dabei ist es, diese Zellen genügend zu trennen, um die Verbreitung von Fehlern zu reduzieren, und dabei ihre Leistungsfähigkeit und Funktionalität beizubehalten. In einem komplexen Infrastruktursystem müssen Dienste miteinander kommunizieren, um Anfragen, Daten, Workloads usw. zu teilen. Wenn wir diese Dienste in Zellen replizieren, müssen wir sorgfältig darüber nachdenken, wie wir die Querkommunikation verwalten. In einer idealen Welt leiten wir den Verkehr von einer fehlerhaften Zelle zu einer fehlerfreien Zelle um. Aber wie gehen wir mit einer „Anfrage des Todes“ um – einer Anfrage, die dazu führt, dass eine Zelle fehlerhaft wird? Wenn wir diese Anfrage auf eine andere Zelle umleiten, kann dies dazu führen, dass auch diese Zelle in der gleichen Weise fehlerhaft wird, die wir zu vermeiden versuchen. Wir müssen Mechanismen finden, um „guten“ Verkehr von fehlerhaften Zellen umzuleiten, wobei wir den Verkehr erkennen und unterdrücken, der dazu führt, dass Zellen fehlerhaft werden.

Kurzfristig haben wir Kopien von Rechendiensten in jeder Rechenzelle bereitgestellt, so dass die meisten Anfragen an das Rechenzentrum von einer einzelnen Zelle bedient werden können. Wir gleichen zudem den Verkehr zellenübergreifend aus. Wenn wir weiter in die Zukunft schauen, haben wir begonnen, einen Dienstentdeckungsvorgang der nächsten Generation zu entwickeln, der von einem Dienstenetz genutzt werden wird, den wir bis 2024 abschließen möchten. Dies wird es uns ermöglichen, anspruchsvolle Richtlinien umzusetzen, die eine zellenübergreifende Kommunikation nur dann zulassen, wenn dies sich nicht negativ auf die Ausfallszellen auswirkt. Ab 2024 wird zudem eine Methode eingeführt, um abhängige Anfragen an eine Dienste-Version in derselben Zelle zu leiten, was den zellenübergreifenden Verkehr minimieren und somit das Risiko einer zellenübergreifenden Übertragung von Fehlern reduzieren wird.

Zu Spitzenzeiten wird über 70 Prozent unseres Back-End-Serviceverkehrs von Zellen bedient, und wir haben viel darüber gelernt, wie man Zellen erstellt. Wir erwarten jedoch weitere Forschung und Tests, während wir unsere Dienste bis 2024 und darüber hinaus weiter migrieren. Im Laufe der Zeit werden diese Schutzwände immer stärker werden.

Die Migration einer durchgehend aktiven Infrastruktur

Roblox ist eine globale Plattform, die Nutzer:innen auf der ganzen Welt unterstützt. Daher können wir Dienste nicht während Nebenzeiten oder „Ausfallzeiten“ verschieben, was den Prozess der Migration all unserer Maschinen in Zellen und das Ausführen unserer Dienste in diesen Zellen weiter verkompliziert. Wir haben Millionen von durchgehend aktiven Erlebnissen, die unterstützt werden müssen, selbst wenn wir die Maschinen, auf denen sie laufen, und die sie unterstützenden Dienste verschieben. Als wir diesen Vorgang begonnen haben, hatten wir nicht Zehntausende von Maschinen einfach ungenutzt herumstehen, die wir für die Migration dieser Workloads nutzen konnten.

Allerdings hatten wir eine geringe Anzahl zusätzlicher Maschinen, die im Hinblick auf zukünftiges Wachstum gekauft wurden. Zu Beginn haben wir neue Zellen mit diesen Maschinen erstellt und anschließend Workloads darauf migriert. Wir legen Wert auf Effizienz und Zuverlässigkeit. Anstatt weitere Maschinen zu kaufen, als uns die „Ersatzmaschinen“ ausgingen, erschufen wir mehr Zellen, indem wir die Maschinen, von denen wir Workloads migriert hatten, löschten und neu bereitgestellten. Dann migrierten wir Workloads auf diese neu bereitgestellten Maschinen und begannen den Vorgang wieder von vorne. Dieser Vorgang ist komplex, da Maschinen ersetzt werden und nicht auf ideale oder geordnete Weise für die Erschaffung von Zellen freigegeben werden. Sie sind physisch über verschiedene Rechenzentrumshallen verteilt, sodass wir sie stückweise bereitstellen müssen. Dies erfordert einen Defragmentierungsprozess auf Hardwareebene, um die Hardware-Standorte mit großen physischen Ausfallbereichen in Einklang zu halten.

Ein Teil unseres Teams für Infrastruktur-Engineering konzentriert sich darauf, bestehende Workloads aus unserer alten oder „prä-Zellen“ Umgebung in Zellen zu migrieren. Diese Arbeit wird fortgesetzt, bis wir Tausende verschiedener Infrastrukturdienste und Tausende von Back-End-Diensten in neu erstellte Zellen migriert haben. Wir gehen davon aus, dass dies das gesamte nächste Jahr in Anspruch nehmen und aufgrund einiger erschwerender Faktoren möglicherweise bis zum Jahr 2025 dauern wird. Zunächst erfordert diese Arbeit die Entwicklung von robusten Werkzeugen. Zum Beispiel benötigen wir Tools, um automatisch eine große Anzahl von Diensten neu auszubalancieren, wenn wir eine neue Zelle bereitstellen, ohne unsere Nutzer:innen zu beeinträchtigen. Wir haben auch Dienste gesehen, die mit Annahmen über unsere Infrastruktur erstellt wurden. Wir müssen diese Dienste überarbeiten, damit sie nicht von Dingen abhängig sind, die sich in der Zukunft ändern könnten, wenn wir in Zellen übergehen. Wir haben auch eine Möglichkeit zur Suche nach bekannten Designmustern implementiert, die nicht gut mit zellulärer Architektur funktionieren, sowie einen systematischen Testprozess für jeden Dienst, der migriert wird. Diese Prozesse helfen uns, mögliche Probleme für Nutzer:innen zu verhindern, die durch einen Dienst verursacht werden, der nicht mit Zellen kompatibel ist.

Heute werden bereits fast 30.000 Maschinen von Zellen verwaltet. Es handelt sich nur um einen Bruchteil unserer gesamten Flotte, aber der Übergang verlief bisher sehr reibungslos, ohne negative Auswirkungen auf die Spieler:innen. Unser ultimatives Ziel ist es, dass unsere Systeme jeden Monat eine Benutzer-Verfügbarkeit von 99,99 Prozent erreichen, was bedeutet, dass wir höchstens 0,01 Prozent der Nutzungsstunden beeinträchtigen würden. Branchenweit kann Ausfallzeit nicht vollständig eliminiert werden, aber unser Ziel ist es, jegliche Ausfallzeit bei Roblox auf ein Maß zu reduzieren, das praktisch kaum wahrnehmbar ist.

Zukunftssicherheit beim Skalieren

Obwohl unsere frühen Bemühungen erfolgreich sind, ist unsere Arbeit an Zellen bei Weitem noch nicht abgeschlossen. Während Roblox weiter wächst, werden wir daran arbeiten, die Effizienz und Widerstandsfähigkeit unserer Systeme durch diese und andere Technologien weiter zu verbessern. Mit der Zeit wird die Plattform zunehmend widerstandsfähig gegenüber Problemen und auftretende Probleme sollten für die Nutzer:innen unserer Plattform immer weniger sichtbar und störend werden.

Zusammenfassend haben wir bisher:

  • Ein zweites Rechenzentrum errichtet und erfolgreich den aktiven/passiven Status erreicht.
  • Zellen in unseren aktiven und passiven Rechenzentren erstellt und erfolgreich mehr als 70 Prozent unseres Back-End-Serviceverkehrs in diese Zellen migriert.
  • Die Anforderungen und Best Practices festgelegt, die zu befolgen sind, um alle Zellen einheitlich zu halten, während wir den Rest unserer Infrastruktur weiter migrieren.
  • Einen kontinuierlichen Prozess gestartet, um stärkere „Schutzwände“ zwischen den Zellen zu errichten.

Da diese Zellen austauschbarer werden, wird es weniger gegenseitige Beeinflussung zwischen den Zellen geben. Dies eröffnet uns interessante Möglichkeiten zur Steigerung der Automatisierung im Bereich Überwachung, Fehlerbehebung und sogar automatischer Workload-Verlagerung.

Im September haben wir auch aktive/aktive Experimente in unseren Rechenzentren gestartet. Dies ist ein weiterer Mechanismus, den wir testen, um die Zuverlässigkeit zu verbessern und die Ausfallzeiten zu minimieren. Diese Experimente haben dazu beigetragen, eine Reihe von Systemdesignmustern, hauptsächlich im Bereich des Datenzugriffs, zu identifizieren, die wir überarbeiten müssen, wenn wir uns auf eine vollständig Aktiv-/Aktiv-Konfiguration zubewegen. Insgesamt war das Experiment erfolgreich genug, um es für den Verkehr einer begrenzten Anzahl unserer Nutzer:innen weiterhin auszuführen.

Wir freuen uns darauf, diese Arbeit weiter voranzutreiben, um eine größere Effizienz und Widerstandsfähigkeit für die Plattform zu schaffen. Diese Arbeit an Zellen und aktiven/aktiven Infrastrukturen, zusammen mit unseren anderen Bemühungen, wird es uns ermöglichen, zu einer zuverlässigen und leistungsstarken Dienstleistung für Millionen von Menschen heranzuwachsen und weiter zu skalieren, während wir daran arbeiten, eine Milliarde Menschen in Echtzeit zu verbinden.