Skip to main content

Comment nous rendons l’infrastructure de Roblox plus efficace et plus résistante

December 7, 2023

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


Technologie

Au fur et à mesure que Roblox s’est développé au cours des 16 dernières années, l’échelle et la complexité de l’infrastructure technique qui prend en charge des millions d’expériences immersives en 3D se sont également accrues. Le nombre de machines que nous prenons en charge a plus que triplé au cours des deux dernières années, passant d’environ 36 000 au 30 juin 2021 à près de 145 000 aujourd’hui. La prise en charge de ces expériences en continu pour des personnes du monde entier nécessite plus de 1 000 services internes. Pour nous aider à contrôler les coûts et la latence du réseau, nous déployons et gérons ces machines dans le cadre d’une infrastructure de cloud privé hybride et sur mesure qui fonctionne principalement dans nos locaux.

Notre infrastructure soutient actuellement plus de 70 millions d’utilisateurs actifs quotidiens dans le monde entier, y compris les créateurs qui dépendent de l’économie de Roblox. Tous ces millions de personnes s’attendent à un niveau de fiabilité très élevé. Compte tenu de la nature immersive de nos expériences, la tolérance à l’égard des décalages ou des temps de latence est extrêmement faible, sans parler des pannes. Roblox est une plateforme de communication et de connexion, où les gens se retrouvent dans des expériences immersives en 3D. Lorsque des personnes communiquent sous forme d’avatars dans un espace immersif, même des retards ou des problèmes mineurs sont plus perceptibles que lors d’un échange de texte ou d’une conférence téléphonique.

En octobre 2021, nous avons connu une panne de système. Au départ, il s’agissait d’un problème sur un composant dans un centre de données. Mais il s’est rapidement propagé pendant que nous enquêtions et a finalement entraîné une panne de 73 heures. À l’époque, nous avons partagé à la fois les détails de ce qui s’est passé et certains des premiers enseignements que nous avons tirés de ce problème. Depuis, nous étudions ces enseignements et nous nous efforçons d’accroître la résilience de notre infrastructure face aux types de défaillances qui surviennent dans tous les systèmes à grande échelle en raison de facteurs tels que les pics de trafic extrêmes, les conditions météorologiques, les pannes matérielles, les bogues logiciels ou tout simplement les erreurs humaines. Lorsque ces défaillances se produisent, comment s’assurer que le problème d’un seul composant, ou d’un groupe de composants, ne se propage pas à l’ensemble du système ? Cette question a été au centre de nos préoccupations au cours des deux dernières années et, bien que le travail se poursuive, ce que nous avons fait jusqu’à présent porte déjà ses fruits. Par exemple, au cours du premier semestre 2023, nous avons économisé 125 millions d’heures d’engagement par mois par rapport au premier semestre 2022. Aujourd’hui, nous partageons le travail que nous avons déjà accompli, ainsi que notre vision à plus long terme pour construire un système d’infrastructure plus résilient.

Construire un filet de protection

Dans les systèmes d’infrastructure à grande échelle, les petites pannes se produisent plusieurs fois par jour. Si une machine a un problème et doit être mise hors service, c’est gérable car la plupart des entreprises maintiennent plusieurs instances de leurs services back-end. Ainsi, lorsqu’une seule instance tombe en panne, d’autres prennent le relais. Pour remédier à ces défaillances fréquentes, les demandes sont généralement paramétrées de manière à ce qu’elles soient automatiquement réessayées en cas d’erreur.

Cela devient un défi lorsqu’un système ou une personne effectue des tentatives de manière trop agressive, ce qui peut permettre à ces défaillances à petite échelle de se propager à travers l’infrastructure vers d’autres services et systèmes. Si le réseau ou un utilisateur effectue des tentatives de manière suffisamment persistante, il finira par surcharger chaque instance de ce service, et potentiellement d’autres systèmes, à l’échelle mondiale. Notre panne de 2021 est le résultat d’un phénomène courant dans les systèmes à grande échelle : Une panne commence par une petite erreur, puis se propage dans le système, prenant de l’ampleur si rapidement qu’il est difficile de la résoudre avant que tout ne tombe en panne.

Au moment de notre panne, nous disposions d’un centre de données actif (dont les composants servaient de backup). Nous devions pouvoir basculer manuellement vers un nouveau centre de données lorsqu’un problème entraînait l’arrêt du centre existant. Notre première priorité était de nous assurer que nous disposions d’un déploiement de sauvegarde de Roblox, et nous avons donc construit cette sauvegarde dans un nouveau centre de données, situé dans une région géographique différente. Cela a permis d’ajouter une protection contre le pire des scénarios : une panne se propageant à un nombre suffisant de composants au sein d’un centre de données pour le rendre totalement inopérant. Nous avons maintenant un centre de données qui gère les charges de travail (actif) et un autre en attente, qui sert de sauvegarde (passif). Notre objectif à long terme est de passer de cette configuration active-passive à une configuration active-active, dans laquelle les deux centres de données gèrent les charges de travail, un équilibreur de charge répartissant les demandes entre eux en fonction de la latence, de la capacité et de l’état de fonctionnement. Une fois cette configuration mise en place, nous espérons obtenir une fiabilité encore plus grande pour l’ensemble de Roblox et être en mesure d’effectuer un basculement presque instantanément plutôt qu’après plusieurs heures.

Passer à une infrastructure cellulaire

Notre priorité suivante était de créer de solides murs de protection contre les explosions à l’intérieur de chaque centre de données afin de réduire le risque de défaillance d’un centre de données entier. Les cellules (que certaines entreprises appellent « clusters ») sont essentiellement un ensemble de machines et c’est ainsi que nous créons ces murs. Nous répliquons les services à la fois à l’intérieur des cellules et d’une cellule à l’autre pour une redondance accrue. En fin de compte, nous voulons que tous les services de Roblox fonctionnent dans des cellules afin qu’ils puissent bénéficier à la fois de murs d’explosion solides et d’une redondance. Si une cellule n’est plus fonctionnelle, elle peut être désactivée en toute sécurité. La réplication entre les cellules permet au service de continuer à fonctionner pendant que la cellule est réparée. Dans certains cas, la réparation de la cellule peut signifier un reprovisionnement complet de la cellule. Dans l’industrie, l’effacement et le reprovisionnement d’une machine individuelle ou d’un petit ensemble de machines sont assez courants, ce qui n’est pas le cas pour une cellule entière, qui contient environ 1 400 machines.

Pour que cela fonctionne, ces cellules doivent être largement uniformes, afin que nous puissions déplacer rapidement et efficacement les charges de travail d’une cellule à l’autre. Nous avons défini certaines exigences auxquelles les services doivent satisfaire avant d’être exécutés dans une cellule. Par exemple, les services doivent être conteneurisés, ce qui les rend beaucoup plus portables et empêche quiconque de modifier la configuration au niveau du système d’exploitation. Nous avons adopté une philosophie d’infrastructure en tant que code pour les cellules : Dans notre référentiel de code source, nous incluons la définition de tout ce qui se trouve dans une cellule afin de pouvoir la reconstruire rapidement à partir de zéro à l’aide d’outils automatisés.

Tous les services ne répondent pas actuellement à ces exigences, c’est pourquoi nous avons travaillé pour aider les propriétaires de services à les satisfaire dans la mesure du possible, et nous avons créé de nouveaux outils pour faciliter la migration des services dans les cellules lorsqu’ils sont prêts. Par exemple, notre nouvel outil de déploiement  » raye  » automatiquement le déploiement d’un service dans les cellules, de sorte que les propriétaires de services n’ont pas à réfléchir à la stratégie de réplication. Ce niveau de rigueur rend le processus de migration beaucoup plus difficile et chronophage, mais le résultat à long terme sera un système où l’on ne peut pas se tromper :

  • Il est beaucoup plus facile de contenir une défaillance et d’éviter qu’elle ne se propage à d’autres cellules ;
  • Nos ingénieurs d’infrastructure peuvent être plus efficaces et agir plus rapidement.
  • Les ingénieurs qui développent les services au niveau du produit qui sont finalement déployés dans les cellules n’ont pas besoin de savoir ou de s’inquiéter des cellules dans lesquelles leurs services sont exécutés.

Relever des défis plus importants

De la même manière que les portes coupe-feu sont utilisées pour contenir les flammes, les cellules agissent comme de solides murs d’explosion au sein de notre infrastructure pour aider à contenir le problème qui déclenche une défaillance au sein d’une seule cellule. À terme, tous les services qui composent Roblox seront déployés de manière redondante à l’intérieur des cellules et entre elles. Une fois ce travail achevé, les problèmes pourraient encore se propager suffisamment pour rendre une cellule entière inopérante, mais il serait extrêmement difficile pour un problème de se propager au-delà de cette cellule. Et si nous parvenons à rendre les cellules interchangeables, la reprise sera nettement plus rapide car nous pourrons basculer sur une autre cellule et éviter que le problème n’affecte les utilisateurs finaux.

Là où le bât blesse, c’est lorsqu’il s’agit de séparer suffisamment ces cellules pour réduire les possibilités de propagation des erreurs, tout en maintenant les performances et le fonctionnement. Dans un système d’infrastructure complexe, les services doivent communiquer entre eux pour partager des requêtes, des informations, des charges de travail, etc. Lorsque nous reproduisons ces services dans les cellules, nous devons réfléchir à la manière dont nous gérons la communication croisée. Dans un monde idéal, nous redirigeons le trafic d’une cellule malsaine vers d’autres cellules saines. Mais comment gérer une « requête de mort », c’est-à-dire une requête qui rend une cellule anormale ? Si nous redirigeons cette requête vers une autre cellule, celle-ci peut devenir malsaine, exactement comme nous essayons de l’éviter. Nous devons trouver des mécanismes pour déplacer le « bon » trafic des cellules malsaines tout en détectant et en étouffant le trafic qui provoque la détérioration des cellules.

À court terme, nous avons déployé des copies des services informatiques dans chaque cellule de calcul afin que la plupart des demandes adressées au centre de données puissent être traitées par une seule cellule. Nous procédons également à l’équilibrage du trafic entre les cellules. À plus long terme, nous avons commencé à construire un processus de découverte de services de nouvelle génération qui sera exploité par un maillage de services, que nous espérons achever en 2024. Cela nous permettra de mettre en œuvre des politiques sophistiquées qui autoriseront les communications entre cellules uniquement lorsqu’elles n’auront pas d’impact négatif sur les cellules de basculement. En 2024, nous disposerons également d’une méthode permettant de diriger les demandes dépendantes vers une version de service située dans la même cellule, ce qui réduira le trafic intercellulaire et, partant, le risque de propagation des défaillances d’une cellule à l’autre.

Au plus fort de l’activité, plus de 70 % du trafic de nos services back-end est desservi à partir de cellules et nous avons beaucoup appris sur la façon de créer des cellules, mais nous prévoyons davantage de recherches et de tests à mesure que nous poursuivons la migration de nos services jusqu’en 2024 et au-delà. Au fur et à mesure que nous progresserons, ces murs anti-explosion deviendront de plus en plus solides.

Migration d’une infrastructure toujours active

Roblox est une plateforme mondiale qui accueille des utilisateurs du monde entier. Nous ne pouvons donc pas déplacer les services pendant les heures creuses, ce qui complique encore le processus de migration de toutes nos machines dans des cellules et l’exécution de nos services dans ces cellules. Nous avons des millions d’expériences toujours actives qui doivent continuer à être prises en charge, même si nous déplaçons les machines sur lesquelles elles s’exécutent et les services qui les prennent en charge. Lorsque nous avons entamé ce processus, nous ne disposions pas de dizaines de milliers de machines inutilisées et disponibles pour migrer ces charges de travail.

Nous disposions toutefois d’un petit nombre de machines supplémentaires achetées en prévision d’une croissance future. Pour commencer, nous avons construit de nouvelles cellules en utilisant ces machines, puis nous y avons transféré les charges de travail. Nous attachons de l’importance à l’efficacité et à la fiabilité, donc plutôt que d’acheter d’autres machines une fois que nous avons épuisé les machines « de réserve », nous avons construit d’autres cellules en effaçant et en reprovisionnant les machines que nous avions migrées. Nous avons ensuite migré les charges de travail sur ces machines reprovisionnées et avons recommencé le processus. Ce processus est complexe : au fur et à mesure que les machines sont remplacées et se libèrent pour être intégrées dans les cellules, elles ne se libèrent pas de manière idéale et ordonnée. Elles sont physiquement fragmentées dans les salles de données, ce qui nous oblige à les approvisionner au coup par coup, ce qui nécessite un processus de défragmentation au niveau du matériel pour que les emplacements du matériel restent alignés sur les domaines de défaillance physique à grande échelle.

Une partie de notre équipe d’ingénieurs en infrastructure se concentre sur la migration des charges de travail existantes de notre ancien environnement, ou « pré-cellule », vers les cellules. Ce travail se poursuivra jusqu’à ce que nous ayons migré des milliers de services d’infrastructure différents et des milliers de services back-end dans des cellules nouvellement construites. Nous prévoyons que cela prendra toute l’année prochaine, voire jusqu’en 2025, en raison de certains facteurs de complication. Tout d’abord, ce travail nécessite la mise en place d’outils robustes. Par exemple, nous avons besoin d’outils pour rééquilibrer automatiquement un grand nombre de services lorsque nous déployons une nouvelle cellule, sans que cela ait un impact sur nos utilisateurs. Nous avons également vu des services construits à partir d’hypothèses sur notre infrastructure. Nous devons réviser ces services pour qu’ils ne dépendent pas d’éléments qui pourraient changer à l’avenir, au fur et à mesure que nous nous déplaçons dans les cellules. Nous avons également mis en place un moyen de rechercher les modèles de conception connus qui ne fonctionneront pas bien avec l’architecture cellulaire, ainsi qu’un processus de test méthodique pour chaque service migré. Ces processus nous aident à éviter tout problème lié à l’utilisateur et dû à l’incompatibilité d’un service avec les cellules.

Aujourd’hui, près de 30 000 machines sont gérées par des cellules. Il ne s’agit que d’une fraction de notre flotte totale, mais la transition s’est faite en douceur jusqu’à présent, sans impact négatif sur les joueurs. Notre objectif ultime est que nos systèmes atteignent un temps de fonctionnement de 99,99 % chaque mois, ce qui signifie que nous ne devrions pas perturber plus de 0,01 % des heures d’engagement. Dans l’ensemble de l’industrie, les temps d’arrêt ne peuvent pas être complètement éliminés, mais notre objectif est de réduire les temps d’arrêt de Roblox à un degré tel qu’ils passent presque inaperçus.

La pérennité à mesure que nous évoluons

Bien que nos premiers efforts soient couronnés de succès, notre travail sur les cellules est loin d’être terminé. Au fur et à mesure que Roblox se développe, nous continuerons à travailler pour améliorer l’efficacité et la résilience de nos systèmes grâce à cette technologie et à d’autres. Au fur et à mesure, la plateforme deviendra de plus en plus résistante aux difficultés, et les problèmes qui surviennent devraient devenir progressivement moins visibles et moins perturbants pour les utilisateurs de notre plateforme.

En résumé, à ce jour, nous avons :

  • Construit un deuxième centre de données et réussi à obtenir le statut actif/passif.
  • créé des cellules dans nos centres de données actifs et passifs et migré avec succès plus de 70 % du trafic de nos services d’arrière-plan vers ces cellules.
  • Mise en place des exigences et des meilleures pratiques que nous devrons suivre pour maintenir l’uniformité de toutes les cellules alors que nous continuons à migrer le reste de notre infrastructure.
  • Lancement d’un processus continu de renforcement des « blast walls » entre les cellules.

À mesure que ces cellules deviennent plus interchangeables, il y aura moins de diaphonie entre elles. Cela ouvre des perspectives très intéressantes en termes d’automatisation de la surveillance, du dépannage et même du déplacement automatique des charges de travail.

En septembre, nous avons également commencé à mener des expériences actives/actives dans nos centres de données. Il s’agit d’un autre mécanisme que nous testons pour améliorer la fiabilité et minimiser les temps de basculement. Ces expériences ont permis d’identifier un certain nombre de modèles de conception du système, principalement autour de l’accès aux données, que nous devons retravailler au fur et à mesure que nous nous dirigeons vers un système entièrement actif-actif. Dans l’ensemble, l’expérience a été suffisamment concluante pour que nous la laissions fonctionner pour le trafic d’un nombre limité de nos utilisateurs.

Nous sommes ravis de continuer à faire avancer ces travaux afin d’améliorer l’efficacité et la résilience de la plateforme. Ce travail sur les cellules et l’infrastructure active-active, ainsi que nos autres efforts, nous permettront de devenir un service public fiable et performant pour des millions de personnes et de continuer à nous développer à mesure que nous nous efforçons de connecter un milliard de personnes en temps réel.