I contenuti di questo sito sono stati tradotti mediante intelligenza artificiale (IA) o tecnologia di traduzione automatica e potrebbero contenere errori.

Skip to content

Come stiamo rendendo l'infrastruttura di Roblox più efficiente e resiliente

Con la crescita di Roblox negli ultimi 16 anni e più, sono cresciute anche le dimensioni e la complessità dell'infrastruttura tecnica che supporta milioni di esperienze collaborative 3D immersive. Il numero di macchine che supportiamo è più che triplicato negli ultimi due anni, passando da circa 36.000 al 30 giugno 2021 a quasi 145.000 oggi. Supportare queste esperienze sempre attive per persone in tutto il mondo richiede più di 1.000 servizi interni. Per aiutarci a controllare i costi e la latenza di rete, distribuiamo e gestiamo queste macchine come parte di un'infrastruttura cloud privata ibrida e costruita su misura che funziona principalmente in loco.  

La nostra infrastruttura supporta attualmente più di 70 milioni di utenti attivi al giorno in tutto il mondo, compresi i creatori che fanno affidamento sull'economia di Roblox per le loro attività. Tutti questi milioni di persone si aspettano un livello di affidabilità molto elevato. Data la natura immersiva delle nostre esperienze, la tolleranza per i ritardi o la latenza è estremamente bassa, per non parlare delle interruzioni di servizio. Roblox è una piattaforma di comunicazione e connessione, dove le persone si riuniscono in esperienze 3D immersive. Quando le persone comunicano tramite i propri avatar in uno spazio immersivo, anche i ritardi o i glitch più lievi sono più evidenti rispetto a quanto lo siano in una chat o in una teleconferenza.

Nell'ottobre 2021 abbiamo subito un'interruzione a livello di sistema. È iniziata in modo circoscritto, con un problema in un componente di un data center. Ma si è diffusa rapidamente mentre stavamo indagando e alla fine ha provocato un'interruzione di 73 ore. All'epoca abbiamo condiviso sia i dettagli su quanto accaduto sia alcune delle nostre prime conclusioni tratte dal problema. Da allora, abbiamo studiato tali insegnamenti e lavorato per aumentare la resilienza della nostra infrastruttura ai tipi di guasti che si verificano in tutti i sistemi su larga scala a causa di fattori quali picchi di traffico estremi, condizioni meteorologiche, guasti hardware, bug software o semplicemente errori umani. Quando si verificano questi guasti, come possiamo garantire che un problema in un singolo componente, o in un gruppo di componenti, non si diffonda all’intero sistema? Questa domanda è stata al centro della nostra attenzione negli ultimi due anni e, sebbene il lavoro sia ancora in corso, ciò che abbiamo fatto finora sta già dando i suoi frutti. Ad esempio, nella prima metà del 2023, abbiamo risparmiato 125 milioni di ore di interazione al mese rispetto alla prima metà del 2022. Oggi condividiamo il lavoro che abbiamo già svolto, nonché la nostra visione a lungo termine per la creazione di un sistema infrastrutturale più resiliente.

Creazione di un sistema di backup

All'interno dei sistemi infrastrutturali su larga scala, si verificano piccoli guasti più volte al giorno. Se una macchina presenta un problema e deve essere messa fuori servizio, la situazione è gestibile perché la maggior parte delle aziende mantiene più istanze dei propri servizi di back-end. Quindi, quando una singola istanza si guasta, le altre ne assumono il carico di lavoro. Per far fronte a questi frequenti guasti, le richieste sono generalmente impostate per riprovare automaticamente se ricevono un errore.

Questo diventa problematico quando un sistema o una persona riprova in modo troppo aggressivo, il che può diventare un modo per far propagare quei guasti su piccola scala attraverso l’infrastruttura ad altri servizi e sistemi. Se la rete o un utente riprova con sufficiente insistenza, alla fine sovraccaricherà ogni istanza di quel servizio, e potenzialmente altri sistemi, a livello globale. La nostra interruzione del 2021 è stata il risultato di qualcosa di abbastanza comune nei sistemi su larga scala: un guasto inizia in piccolo, poi si propaga attraverso il sistema, diventando così grande così rapidamente che è difficile risolverlo prima che tutto vada in tilt. 

Al momento dell'interruzione, avevamo un solo data center attivo (con componenti al suo interno che fungevano da backup). Avevamo bisogno della possibilità di effettuare manualmente il failover verso un nuovo data center quando un problema causava il blocco di quello esistente. La nostra priorità era garantire una distribuzione di backup di Roblox, quindi abbiamo realizzato quel backup in un nuovo data center, situato in una regione geografica diversa. Ciò ha aggiunto protezione per lo scenario peggiore: un'interruzione che si diffonde a un numero sufficiente di componenti all'interno di un data center da renderlo completamente inoperativo. Ora abbiamo un data center che gestisce i carichi di lavoro (attivo) e uno in standby, che funge da backup (passivo). Il nostro obiettivo a lungo termine è passare da questa configurazione attivo-passivo a una configurazione attivo-attivo, in cui entrambi i data center gestiscono i carichi di lavoro, con un bilanciatore di carico che distribuisce le richieste tra di essi in base a latenza, capacità e integrità. Una volta che questo sarà operativo, prevediamo di avere un'affidabilità ancora maggiore per tutto Roblox e di essere in grado di effettuare il failover quasi istantaneamente anziché in diverse ore.

Passaggio a un'infrastruttura cellulare

La nostra priorità successiva era quella di creare solide barriere protettive all'interno di ogni data center per ridurre la possibilità di un guasto dell'intero data center. Le celle (alcune aziende le chiamano cluster) sono essenzialmente un insieme di macchine e rappresentano il modo in cui stiamo creando queste barriere. Replichiamo i servizi sia all'interno che tra le celle per una maggiore ridondanza. In definitiva, vogliamo che tutti i servizi di Roblox funzionino in celle in modo che possano beneficiare sia di solide barriere protettive che di ridondanza. Se una cella non è più funzionante, può essere disattivata in tutta sicurezza. La replica tra le celle consente al servizio di continuare a funzionare mentre la cella viene riparata. In alcuni casi, la riparazione di una cella potrebbe comportare un completo riprovisioning della stessa. Nel settore, la cancellazione e il riprovisioning di una singola macchina, o di un piccolo insieme di macchine, è piuttosto comune, ma farlo per un'intera cella, che contiene circa 1.400 macchine, non lo è. 

Affinché ciò funzioni, queste celle devono essere in gran parte uniformi, in modo da poter spostare i carichi di lavoro da una cella all'altra in modo rapido ed efficiente. Abbiamo stabilito alcuni requisiti che i servizi devono soddisfare prima di essere eseguiti in una cella. Ad esempio, i servizi devono essere containerizzati, il che li rende molto più portabili e impedisce a chiunque di apportare modifiche alla configurazione a livello di sistema operativo. Abbiamo adottato una filosofia di "infrastruttura come codice" per le celle: nel nostro repository di codice sorgente includiamo la definizione di tutto ciò che si trova in una cella, in modo da poterla ricostruire rapidamente da zero utilizzando strumenti automatizzati. 

Non tutti i servizi soddisfano attualmente questi requisiti, quindi abbiamo lavorato per aiutare i proprietari dei servizi a soddisfarli ove possibile e abbiamo creato nuovi strumenti per facilitare la migrazione dei servizi nelle celle quando saranno pronti. Ad esempio, il nostro nuovo strumento di distribuzione "distribuisce" automaticamente la distribuzione di un servizio tra le celle, in modo che i proprietari dei servizi non debbano preoccuparsi della strategia di replica. Questo livello di rigore rende il processo di migrazione molto più impegnativo e dispendioso in termini di tempo, ma il risultato a lungo termine sarà un sistema in cui: 

  • È molto più facile contenere un guasto e impedire che si diffonda ad altre celle; 
  • I nostri ingegneri dell'infrastruttura possono essere più efficienti e agire più rapidamente; e 
  • Gli ingegneri che realizzano i servizi a livello di prodotto che vengono infine distribuiti nelle celle non devono sapere né preoccuparsi di quali celle ospitano i loro servizi.

Risolvere sfide più grandi

Analogamente al modo in cui le porte tagliafuoco vengono utilizzate per contenere le fiamme, le celle fungono da solide pareti anti-esplosione all'interno della nostra infrastruttura per aiutare a contenere qualsiasi problema che provochi un guasto all'interno di una singola cella. Alla fine, tutti i servizi che compongono Roblox saranno distribuiti in modo ridondante all'interno e tra le celle. Una volta completato questo lavoro, i problemi potrebbero comunque propagarsi abbastanza da rendere inoperativa un'intera cella, ma sarebbe estremamente difficile che un problema si propagasse oltre quella cella. E se riusciremo a rendere le celle intercambiabili, il ripristino sarà significativamente più veloce perché saremo in grado di effettuare il failover su una cella diversa ed evitare che il problema abbia un impatto sugli utenti finali. 

La difficoltà sta nel separare queste celle in modo tale da ridurre la possibilità di propagazione degli errori, mantenendo al contempo le prestazioni e la funzionalità. In un sistema infrastrutturale complesso, i servizi devono comunicare tra loro per condividere query, informazioni, carichi di lavoro, ecc. Man mano che replichiamo questi servizi nelle celle, dobbiamo riflettere attentamente su come gestire la comunicazione incrociata. In un mondo ideale, reindirizziamo il traffico da una cella non funzionante ad altre celle funzionanti. Ma come gestiamo una "query della morte", quella che sta causando il malfunzionamento di una cella? Se reindirizziamo quella query verso un'altra cella, potremmo causare il malfunzionamento di quella cella, proprio ciò che stiamo cercando di evitare. Dobbiamo trovare meccanismi per spostare il traffico "buono" dalle celle non funzionanti, individuando e bloccando al contempo il traffico che sta causando il malfunzionamento delle celle. 

Nel breve termine, abbiamo distribuito copie dei servizi di elaborazione in ciascuna cella di calcolo in modo che la maggior parte delle richieste al data center possa essere gestita da una singola cella. Stiamo inoltre bilanciando il carico del traffico tra le celle. Guardando più in là, abbiamo iniziato a costruire un processo di service discovery di nuova generazione che sarà sfruttato da un service mesh, che speriamo di completare nel 2024. Questo ci consentirà di implementare politiche sofisticate che permetteranno la comunicazione tra celle solo quando non avrà un impatto negativo sulle celle di failover. Nel 2024 sarà inoltre disponibile un metodo per indirizzare le richieste dipendenti verso una versione del servizio nella stessa cella, il che ridurrà al minimo il traffico tra celle e quindi il rischio di propagazione dei guasti tra celle.

Nei momenti di picco, oltre il 70% del traffico dei nostri servizi di back-end viene gestito al di fuori delle celle e abbiamo imparato molto su come creare le celle, ma prevediamo ulteriori ricerche e test man mano che continuiamo a migrare i nostri servizi fino al 2024 e oltre. Man mano che procediamo, queste barriere di protezione diventeranno sempre più solide.

Migrazione di un'infrastruttura sempre attiva

Roblox è una piattaforma globale che supporta utenti in tutto il mondo, quindi non possiamo spostare i servizi durante le ore di minor traffico o i "periodi di inattività", il che complica ulteriormente il processo di migrazione di tutte le nostre macchine in celle e dei nostri servizi per funzionare in quelle celle. Abbiamo milioni di esperienze sempre attive che devono continuare a essere supportate, anche mentre spostiamo le macchine su cui girano e i servizi che le supportano. Quando abbiamo iniziato questo processo, non avevamo decine di migliaia di macchine inutilizzate e disponibili su cui migrare questi carichi di lavoro. 

Avevamo, tuttavia, un piccolo numero di macchine aggiuntive che erano state acquistate in previsione di una crescita futura. Per iniziare, abbiamo costruito nuove celle utilizzando quelle macchine, poi abbiamo migrato i carichi di lavoro su di esse. Diamo valore sia all'efficienza che all'affidabilità, quindi, invece di andare a comprare altre macchine una volta esaurite quelle "di riserva", abbiamo creato altre celle cancellando e riprovisionando le macchine da cui avevamo effettuato la migrazione. Abbiamo quindi migrato i carichi di lavoro su quelle macchine riprovisionate e abbiamo ricominciato il processo da capo. Questo processo è complesso: man mano che le macchine vengono sostituite e si liberano per essere integrate nelle celle, non si liberano in modo ideale e ordinato. Sono fisicamente frammentate tra le sale dati, costringendoci a provisionarle in modo frammentario, il che richiede un processo di deframmentazione a livello hardware per mantenere le posizioni hardware allineate con i domini di guasto fisico su larga scala. 

Una parte del nostro team di ingegneria dell'infrastruttura si concentra sulla migrazione dei carichi di lavoro esistenti dal nostro ambiente legacy, o "pre-cell", alle celle. Questo lavoro continuerà fino a quando non avremo migrato migliaia di diversi servizi di infrastruttura e migliaia di servizi di back-end nelle celle di nuova costruzione. Prevediamo che ciò richiederà tutto il prossimo anno e forse fino al 2025, a causa di alcuni fattori di complicazione. Innanzitutto, questo lavoro richiede la creazione di strumenti robusti. Ad esempio, abbiamo bisogno di strumenti per ribilanciare automaticamente un gran numero di servizi quando distribuiamo una nuova cella, senza impatti sui nostri utenti. Abbiamo anche riscontrato servizi che sono stati realizzati partendo da ipotesi relative alla nostra infrastruttura. Dobbiamo rivedere questi servizi in modo che non dipendano da elementi che potrebbero cambiare in futuro man mano che passiamo alle celle. Abbiamo inoltre implementato sia un metodo per individuare i modelli di progettazione noti che non funzionano bene con l'architettura cellulare, sia un processo di test metodico per ogni servizio migrato. Questi processi ci aiutano a prevenire eventuali problemi per gli utenti causati dall'incompatibilità di un servizio con le celle.

Oggi, quasi 30.000 macchine sono gestite da celle. Si tratta solo di una piccola parte del nostro parco macchine totale, ma finora la transizione è stata molto fluida, senza alcun impatto negativo sui giocatori. Il nostro obiettivo finale è che i nostri sistemi raggiungano un tempo di attività per gli utenti del 99,99% ogni mese, il che significa che non interromperemmo più dello 0,01% delle ore di utilizzo. A livello di settore, i tempi di inattività non possono essere completamente eliminati, ma il nostro obiettivo è ridurre qualsiasi tempo di inattività di Roblox a un livello tale da renderlo quasi impercettibile.

Prepararci al futuro mentre cresciamo

Sebbene i nostri primi sforzi si stiano rivelando efficaci, il nostro lavoro sulle celle è lungi dall'essere concluso. Man mano che Roblox continua a crescere, continueremo a lavorare per migliorare l'efficienza e la resilienza dei nostri sistemi attraverso questa e altre tecnologie. Man mano che procediamo, la piattaforma diventerà sempre più resiliente ai problemi e qualsiasi problema che si verifichi dovrebbe diventare progressivamente meno visibile e meno dirompente per le persone sulla nostra piattaforma.

In sintesi, ad oggi abbiamo: 

  • Costruito un secondo data center e raggiunto con successo lo stato attivo/passivo. 
  • Creato delle celle nei nostri data center attivi e passivi e migrato con successo oltre il 70% del traffico dei nostri servizi di back-end verso queste celle.
  • Definito i requisiti e le best practice che dovremo seguire per mantenere tutte le celle uniformi mentre continuiamo a migrare il resto della nostra infrastruttura. 
  • Avviato un processo continuo di costruzione di "barriere di protezione" più solide tra le celle. 

Man mano che queste celle diventeranno più intercambiabili, ci sarà meno interferenza tra di esse. Questo ci apre alcune opportunità molto interessanti in termini di aumento dell'automazione per quanto riguarda il monitoraggio, la risoluzione dei problemi e persino lo spostamento automatico dei carichi di lavoro. 

A settembre abbiamo anche iniziato a condurre esperimenti active/active nei nostri data center. Si tratta di un altro meccanismo che stiamo testando per migliorare l'affidabilità e ridurre al minimo i tempi di failover. Questi esperimenti hanno aiutato a identificare una serie di modelli di progettazione del sistema, principalmente relativi all'accesso ai dati, che dobbiamo rielaborare mentre ci avviciniamo a diventare completamente active-active. Nel complesso, l'esperimento ha avuto un successo tale da lasciarlo in esecuzione per il traffico proveniente da un numero limitato dei nostri utenti. 

Siamo entusiasti di portare avanti questo lavoro per garantire maggiore efficienza e resilienza alla piattaforma. Questo lavoro sulle celle e sull'infrastruttura active-active, insieme alle nostre altre iniziative, ci consentirà di diventare un servizio affidabile e ad alte prestazioni per milioni di persone e di continuare a crescere mentre lavoriamo per connettere un miliardo di persone in tempo reale.