Utilizzo di Cloud SQL per MySQL di seconda generazione come database di backend per giochi per dispositivi mobili

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

Un pattern ben testato per la creazione di un backend di gioco online utilizza un database relazionale, come MySQL. Questo database archivia i dati relativi allo stato globale e alla persistenza dei giochi. Per i giochi basati su sessione di base, il database non contiene nulla di più complesso dei risultati finali delle corrispondenze. Per i giochi online di grandi dimensioni (MMO) e di lunga durata, potrebbe essere un insieme molto complicato di tabelle interconnesse che includono i progressi dei giocatori e l'inventario. La velocità delle query nel livello del database del backend influisce direttamente sull'esperienza di reattività dell'utente nel client di gioco.

Sebbene questo pattern sia familiare, la maggior parte dei team di sviluppo di giochi non ha un amministratore di database dedicato e, mano a mano che il database cresce e le relazioni diventa più complessa, l'amministrazione può diventare un compito che molti team preferirebbero delegare. Per i giochi per dispositivi mobili basati su turni di piccole e medie dimensioni, un database come Google Cloud SQL può essere una scelta eccellente. Cloud SQL per MySQL di seconda generazione offre un'istanza di MySQL completamente ospitata e gestita con prestazioni solide, operazioni minime e backup automatici.

Progettazione di pattern dei database frontali

Panoramica dell'architettura di database.

Il paradigma di microservizi è utile per i backend di database di giochi per dispositivi mobili. Una struttura comune è fare in modo che il database sia preceduto da un servizio di database, che è formato da un pool di processi worker che accettano richieste di query dal frontend del gioco, le eseguono in base al database e restituiscono i risultati.

Vantaggi del pattern del database frontali di servizi

Avere una query di servizio intermediario per il database per conto dei tuoi server di gioco presenta diversi vantaggi:

  • Aumento della disponibilità: i database spesso limitano il numero di connessioni simultanee. L'utilizzo di un servizio disaccoppia il numero di server di gioco che possono effettuare richieste al database dalle connessioni massime consentite.
  • Tolleranza di errore: i servizi di database possono essere creati per elaborare temporaneamente le richieste in caso di problemi.
  • Richieste ottimizzate: un servizio di database può ottimizzare le richieste di database, fornendo:
    • Convalida delle query.
    • Priorità query.
    • Controllo del flusso della query.
    • Memorizzazione nella cache in memoria.
  • Astrazione del database: finché il contratto di servizio è soddisfatto, il servizio di database e il supporto del database possono essere sostituiti senza modifiche ai server di gioco frontend. Questa progettazione rende possibile l'utilizzo di database diversi negli ambienti di sviluppo o QA oppure di eseguire la migrazione a una tecnologia di database diversa in produzione.

Un pattern di database frontali per i giochi

Il seguente diagramma illustra come creare un solido pattern di database front-service utilizzando i servizi Google Cloud Platform.

Pattern di database utilizzando Google Cloud Platform.

È possibile creare un solido pattern di database frontaliero utilizzando i seguenti componenti:

  • Server di gioco dedicati/frontend: le applicazioni client di gioco si connettono direttamente ai server di gioco, di conseguenza sono un servizio di frontend. I server di gioco dedicati sono in genere eseguibili personalizzati, creati con il motore di gioco, che devono essere eseguiti su hardware virtualizzato come le VM di Google Compute Engine. Se stai scrivendo un gioco in cui l'interazione online può essere modellata con una semantica di richieste/risposte in stile HTTP, anche Google App Engine è una buona scelta.

  • Comunicazione con server di gioco con i servizi di database: spesso è modellata utilizzando lo stile di accesso create, read, update ed delete (CRUD), rendendo un'API REST o un endpoint gRPC su Compute Engine un'ottima scelta.

  • Comunicazione degli endpoint API/RPC con un pool di worker del database: un caso classico per l'inserimento in coda di scelte popolari sono i middleware autogestiti e open source in coda come RabbitMQ o ZeroMQ. Su Cloud Platform puoi utilizzare Cloud Pub/Sub sicuro, durevole e ad alta disponibilità. Offre una soluzione di coda gestita senza la necessità di gestire i server.

  • Lavoratori di database che si connettono a Cloud SQL di seconda generazione: i worker di database possono essere scritti in qualsiasi linguaggio che fornisce un metodo di accesso a MySQL aggiornato. Questi worker possono essere gestiti manualmente su Compute Engine o pacchettizzati in container Docker per essere gestiti facilmente mediante la DSL di Kubernetes su Google Kubernetes Engine.

Ci sono alcune limitazioni da considerare quando si utilizza Cloud SQL di seconda generazione:

  • Limite di dimensioni del database di 10 TB.
  • Limite di connessioni a 4000 connessioni simultanee.
  • Mancanza del supporto di NDB (sharding), anche se le repliche sono supportate.

Per risolvere questi problemi:

  • Scegli un modello di dati che ottimizzi la quantità di dati archiviati.

  • Incorporare processi che spostano i dati a cui si accede raramente dal database principale e in un data warehouse, come Google BigQuery.

  • Utilizza un pattern in cui i server di gioco accedono al database tramite un microservizio. Anche se il numero di player è sufficientemente basso da consentire l'accesso diretto al database dei server di gioco, esistono numerosi vantaggi rispetto all'accoppiamento del livello del database dal server di gioco: alla coda, al livellamento della frequenza di query, alla tolleranza di errore della connessione e così via. Inoltre, il tentativo di aggiungere un livello di accesso al database separato dopo che il gioco è diventato popolare può causare tempi di inattività e perdita di entrate.

  • Esegui l'analisi dei giochi e la telemetria del player rispetto a una replica di sola lettura del database. Ciò impedisce alla tua analisi di influire sulla reattività del database. Cloud SQL per MySQL di seconda generazione consente la replica MySQL standard e puoi dimensionare la tua seconda istanza in modo appropriato per le query di analisi per mantenere i costi marginali.

Design di esempio: social media player per giocatori singoli (MASS)

Un paradigma emergente nei giochi nell'ultimo decennio è costituito da un enorme numero di giocatori singoli che giocano contemporaneamente online, con meccanismi social quali il prestito di unità e le unità pubblicitarie e le classifiche sono gli unici punti di contatto tra i giocatori. Esempi di giochi MASS includono Puzzle & DragonsTM e Monster StrikeTM. I giochi MASS mobile sono progettati per essere economici con la comunicazione client/server. In questo modo gli utenti possono godersi il gioco anche con una connettività limitata o sporadica. Il modello di dati di un gioco come questo, in cui quasi tutto lo spazio di archiviazione permanente è correlato al meta gioco (unità di raccolta e mantenimento della valuta del giocatore), genera due tipi di oggetti di base da archiviare nel database. Questi oggetti possono essere facilmente manipolati utilizzando i meccanismi CRUD.

Oggetti player, che monitorano:

  • Gioco e valute reali.
  • Numero totale di slot di inventario per unità.
  • Resistenza.
  • Esperienza.

Oggetti unità, che monitorano:

  • Proprietario (ID giocatore).
  • Esperienza.
  • Costo da acquisire.
  • Unità inventario.

Per meno di 100.000 giocatori, questo modello di dati si inserisce perfettamente in un database relazionale come Cloud SQL di seconda generazione.

Mimus

Mimus è un'applicazione di gioco per dispositivi mobili MASS fittizio con un backend nello stile di Puzzle and DragonsTM o Monster StrikeTM. Si presume che ogni giocatore possa accedere da un solo dispositivo alla volta e che deve completare qualsiasi azione prima di avviarne un altro. Con Mimus puoi eseguire carichi di lavoro simulati per valutare la capacità ottimale dell'architettura, che in genere si basa sul numero di utenti simultanei (CCU).

Puoi trovare il codice sorgente di Mimus all'indirizzo https://github.com/GoogleCloudPlatform/mimus-game-simulator.

Panoramica dell'architettura di Mimus

Simulazione di client Mimus all'interno del server Mimus

Nei giochi MASS, la frequenza con cui il client di gioco genera query di database può essere controllata dallo sviluppatore di giochi richiedendo al player di visualizzare le animazioni e di interagire con il client di gioco per continuare. Mimus simula queste strategie di limitazione della frequenza con sleep() chiamate. In questo modo, Mimus simula una ragionevole approssimazione del carico del database per client eseguendo il maggior numero di processi quanti i giocatori simulati. Questa viene orchestrata in modo efficiente utilizzando un pod client/server Mimus containerizzato, in un cluster Kubernetes, che genera query rispetto al database.

Il client di gioco Mimus simula la comunicazione con il server di backend utilizzando un loop continuo che chiama direttamente le procedure del server Mimus, scegliendo chiamate di funzione in base allo stato del player e al suo inventario.

Le azioni del giocatore simulate da Mimus includono:

  • Facciamo una partita.
  • Valuta di acquisto.
  • Valuta di spesa.
  • Livellamento o evoluzione delle unità.

Ognuna di queste azioni viene implementata come più interazioni CRUD con gli oggetti del player o dell'unità, manipolate dal client attraverso le chiamate al server Mimus. Il server Mimus effettua queste richieste di database utilizzando l'API di database sincrona Mimus. Questa API è un modulo Python importato dal server Mimus e può essere configurato per testare diverse implementazioni del backend del database.

Comunicazione dell'API del database Mimus con il pool di worker del database Mimus

Il seguente diagramma illustra la comunicazione tra il server Mimus e il servizio di database.

Progettazione della comunicazione di Mimus.

L'API Mimus database accetta gruppi di query di database e restituisce i risultati. Pubblica questi batch come messaggi Cloud Pub/Sub e attende che i risultati vengano restituiti tramite Redis. Prima di inviare un messaggio, l'API del database convalida tutti i valori che saranno scritti nel database e contrassegna il messaggio con un ID transazione univoco. Il messaggio viene quindi pubblicato in un argomento Work in Cloud Pub/Sub. Successivamente, l'API del database esegue il loop, eseguendo il polling per l'esistenza dell'ID transazione come chiave Redis. I risultati nel valore della chiave vengono quindi recuperati dall'API del database e restituiti al server Mimus, da cui sono resi disponibili al client Mimus.

Considerazioni sulla selezione delle comunicazioni

Mimus utilizza Cloud Pub/Sub per la comunicazione delle query in attesa, perché le azioni dell'utente richiedono durabilità e affidabilità della distribuzione. Mimus utilizza Redis per comunicare i risultati, dove la durabilità e l'affidabilità sono meno critiche. Se i risultati vengono persi a causa di un errore dell'applicazione o di un errore Redis, il client Mimus esegue nuovamente una query per ottenere i risultati finali dal database. Utilizzando le transazioni in un database relazionale, ti garantisci che sono state eseguite tutte le modifiche richieste o nessuna di queste. Il raro caso in cui Mimus abbia bisogno di effettuare una seconda richiesta è considerato un compromesso accettabile in cambio della semplicità e della velocità di recupero fornite da Redis. Per mantenere l'utilizzo di Redis ragionevole, i risultati delle richieste possono scadere da Redis dopo trenta secondi.

Pool di worker del database Mimus

Il pool di worker del database Mimus contiene più processi in esecuzione su Kubernetes Engine. Ogni istanza di container in esecuzione esegue il polling dell'argomento WorkCloud Pub/Sub in un loop infinito per i nuovi messaggi. Quando riceve un messaggio, esegue le query nel messaggio utilizzando il modulo Python MySQLdb. Un singolo messaggio rappresenta una transazione relazionale e può contenere più query. Tutte le query nel messaggio devono essere completate prima di essere impegnate nel database. Una volta completate o non riuscite le query, il worker del database pubblica i risultati in Redis in base all'ID transazione ricevuto come parte del messaggio originale.

Database Mimus

Il database relazionale a supporto del servizio di database Mimus è un'istanza Cloud SQL per MySQL di seconda generazione. Durante la creazione dell'istanza, puoi selezionare configurazioni di macchine fino a 32 core e 208 GB di RAM, con dimensioni del disco fino a 10 TB. Oltre a supportare le repliche, le istanze di Cloud SQL di seconda generazione sono configurate per eseguire i backup regolari per impostazione predefinita. Se hai bisogno di un'ulteriore correzione di MySQL, puoi impostare flag MySQL personali sull'istanza Cloud SQL. Puoi trovare ulteriori informazioni sulla configurazione nella documentazione di Cloud SQL.

Conclusioni dal test di Cloud SQL con Mimus

Tipo di macchina SG di Cloud SQL Numero suggerito di utenti in contemporanea
n1-standard-4 15.000
n1-standard-8 30.000
n1-standard-16 60.000
n1-standard-32 120.000
n1-highmem-8 50.000
n1-highmem-16 100.000
n1-highmem-32 200.000

Quando utilizzi il cablaggio di test Mimus per simulare 100.000 utenti simultanei rispetto a un'istanza Cloud SQL per MySQL di seconda generazione creata su un'istanza Compute Engine n1-highmem-16, il tempo di risposta alle query è rimasto sotto i 2 secondi durante il test.

Se stai creando un gioco per dispositivi mobili MASS e devi supportare centinaia di migliaia di giocatori simultanei, un pattern di database frontali basato su servizio e basato su Cloud SQL per MySQL di seconda generazione può fornire le prestazioni necessarie. Quando il gioco aumenta di popolarità, puoi introdurre istanze Cloud SQL aggiuntive, sottoposte a sharding o come repliche, e una strategia di memorizzazione nella cache Redis o Memcached a livello di servizio di database per mantenere le prestazioni a livelli accettabili.

Per i giochi con meno utenti in contemporanea previsti, puoi utilizzare un tipo di macchina più piccolo per ridurre i costi.

Per i giochi con milioni di CCU previste, dovresti prendere in considerazione un database SQL, come Google Cloud Datastore o Google Cloud Bigtable, con caratteristiche di scalabilità e prestazioni elevate.

Passaggi successivi

  • Esplora architetture di riferimento, diagrammi e best practice su Google Cloud. Dai un'occhiata al nostro Cloud Architecture Center.