Utiliser Cloud SQL pour MySQL deuxième génération comme base de données de backend pour jeu mobile

Un backend éprouvé de jeu en ligne utilise une base de données relationnelle, telle que MySQL. Cette base de données stocke les données d'état du jeu et les données persistantes essentielles. Pour les jeux basiques fonctionnant par sessions, la base de données ne contient rien de plus que le résultat final des parties. Pour les grands jeux en ligne massivement multijoueurs (MMOG, Massively Multiplayer Online Game), il peut s'agir d'un ensemble extrêmement complexe de tableaux interreliés qui contiennent la progression et l'inventaire des joueurs. La vitesse des requêtes dans la couche de base de données de votre backend affecte directement l'expérience de l'utilisateur concernant la réactivité du jeu.

Bien que ce modèle soit familier, la plupart des équipes de développement de jeux ne disposent pas d'un administrateur de base de données dédié. Au fur et à mesure que la taille de la base de données augmente et que les relations se complexifient, l'administration peut devenir une tâche que de nombreuses équipes préfèrent déléguer. Pour les jeux mobiles de petite et moyenne taille, asynchrones et fonctionnant par tours, une base de données telle que Google Cloud SQL peut être un excellent choix. Cloud SQL pour MySQL deuxième génération offre une instance entièrement hébergée et gérée de MySQL avec des performances solides, des opérations minimales et des sauvegardes automatisées.

Conception de modèle de base de données orientée service

Présentation de l'architecture de base de données

Le paradigme des microservices est utile pour les backends de bases de données de jeux mobiles. Une conception courante consiste à faire en sorte que la base de données soit interfacée par un service de base de données, constitué d'un pool de processus de travail qui accepte les demandes de requête de l'interface du jeu, exécute ces requêtes sur la base de données et renvoie les résultats.

Avantages du modèle de base de données orientée service

Le fait d'avoir un service intermédiaire qui interroge la base de données pour le compte de vos serveurs de jeux présente plusieurs avantages :

  • Une disponibilité accrue : Les bases de données limitent souvent le nombre de connexions simultanées. L'utilisation d'un service découple le nombre de serveurs de jeux qui peuvent envoyer des requêtes à la base de données avec le nombre maximal de connexions autorisées.
  • Une tolérance aux pannes : Des services de base de données peuvent être créés pour traiter temporairement les requêtes lorsque la base de données rencontre un problème.
  • Des requêtes optimisées : Un service de base de données peut optimiser les requêtes de base de données, en établissant :
    • une validation des requêtes ;
    • une priorisation des requêtes ;
    • un contrôle du débit des requêtes ;
    • une mise en cache en mémoire pour la lecture.
  • Une abstraction de la base de données : Tant que le contrat de service est rempli, le service de base de données et la base de données de sauvegarde peuvent être remplacés sans modification sur les serveurs de jeu d'interface. Cette conception permet d'utiliser plusieurs bases de données dans les environnements de développement ou de contrôle qualité, ou de migrer vers une autre technologie de base de données en production.

Modèle de base de données orientée service pour les jeux

Le schéma suivant représente la façon dont vous pouvez créer un modèle robuste de base de données orientée service avec les services Google Cloud Platform.

Modèle de base de données qui utilise Google Cloud Platform

Un modèle robuste de base de données orientée service peut être créé en utilisant les composants suivants :

  • Des serveurs/interfaces de jeu dédiés : Les applications clientes du jeu se connectent directement aux serveurs de jeux, ce qui en fait un service d'interface. Les serveurs de jeux dédiés sont généralement des exécutables personnalisés, créés avec le moteur du jeu, qui doivent s'exécuter sur du matériel virtualisé tel que les VM Google Compute Engine. Si vous développez un jeu où l'interaction en ligne peut être modélisée avec une sémantique requête-réponse de type HTTP, Google App Engine convient également.

  • Une communication entre le serveur de jeu et les services de base de données : Cette communication est souvent modélisée en utilisant le style d'accès CRUD (créer, lire, mettre à jour, supprimer), ce qui fait qu'une API REST ou qu'un point de terminaison gRPC sur Compute Engine est un excellent choix.

  • Une communication de l'API/du point de terminaison RPC vers un pool de nœuds de calcul de base de données : Classiquement, des intergiciels de file d'attente, autogérés et Open Source, tels que RabbitMQ ou ZeroMQ, sont utilisés. Sur Cloud Platform, vous pouvez utiliser le canal Google Cloud Pub/Sub qui est sécurisé, durable et hautement disponible. Il offre une solution de mise en file d'attente gérée, sans avoir besoin de gérer des serveurs.

  • Nœuds de calcul de base de données se connectant à Cloud SQL deuxième génération : Les nœuds de calcul de base de données peuvent être écrits dans tout langage qui fournit une méthode d'accès à MySQL à jour. Ces nœuds de calcul peuvent être gérés manuellement sur Compute Engine, ou intégrés à des conteneurs Docker pour être facilement gérés en utilisant Kubernetes DSL sur Google Kubernetes Engine.

Certaines limites sont à prendre en compte lors de l'utilisation de Cloud SQL deuxième génération :

  • Taille de la base de données limitée à 10 To.
  • Nombre de connexions limité à 4 000 connexions simultanées.
  • Incompatibilité avec NDB (partition), bien que les instances dupliquées soient compatibles.

Pour traiter ces éléments, procédez comme suit :

  • Choisissez un modèle de données qui optimise la quantité de données stockées.

  • Intégrez des processus qui déplacent les données rarement utilisées, de la base de données principale vers un entrepôt de données (par exemple, Google BigQuery).

  • Utilisez un modèle dans lequel les serveurs de jeux accèdent à la base de données par le biais d'un microservice. Même si le nombre de joueurs est peu élevé et que vos serveurs de jeux peuvent accéder directement à la base de données, le découplage de la couche de base de données du serveur de jeu présente de nombreux avantages : mise en file d'attente, nivellement du nombre de requêtes, tolérance aux erreurs de connexion, etc. En outre, le fait d'ajouter une couche d'accès distincte à la base de données lorsque votre jeu a du succès peut entraîner des temps d'arrêt et une perte de revenus.

  • Exécutez les données analytiques du jeu et les données de télémétrie des joueurs sur une instance dupliquée en lecture seule de la base de données. Cette technique empêche l'analyse d'avoir un impact sur la réactivité de la base de données. Cloud SQL pour MySQL de deuxième génération permet une réplication MySQL standard. Vous pouvez dimensionner votre seconde instance de manière appropriée pour les requêtes analytiques afin de maintenir des coûts marginaux.

Exemple de conception : jeu MASS (Massively Single-player Social)

Un paradigme de jeu qui a émergé au cours de la dernière décennie consiste en un nombre important de joueurs individuels qui jouent simultanément sur des sessions en ligne. Des mécanismes sociaux comme l'emprunt d'unités, la vente d'unités et les classements sont les seuls points de contact entre les joueurs. Exemples de jeux MASS : "Puzzle et Dragons™" et "Monster Strike™". Les jeux mobiles MASS sont conçus pour que la communication client/serveur soit la plus restreinte possible. Cela permet aux utilisateurs de profiter de leur jeu, même avec une connectivité limitée ou sporadique. Le modèle de données d'un jeu comme celui-ci, où presque tout le stockage d'état persistant est associé au métajeu (collecte d'unités et gestion de la monnaie du joueur), implique le stockage dans la base de données de deux types d'objets de base. Ces objets peuvent être facilement manipulés en utilisant des mécanismes CRUD.

Objets des joueurs, qui suivent :

  • le jeu et les monnaies réelles ;
  • le nombre total d'emplacements d'inventaire unitaires ;
  • l'endurance ;
  • l'expérience.

Objets unitaires, qui suivent :

  • le propriétaire (ID du joueur) ;
  • l'expérience ;
  • le coût d'acquisition ;
  • l'inventaire des unités.

Pour un nombre de joueurs inférieur à 100 000, ce modèle de données s'intègre bien dans une base de données relationnelle telle que Cloud SQL de deuxième génération.

Mimus

Mimus est une simulation de jeu mobile MASS avec un backend de type "Puzzle and Dragons™" ou "Monster Strike™". Il suppose que chaque joueur ne peut être connecté qu'à un seul appareil à la fois, et que chaque joueur doit terminer une action avant d'en commencer une autre. Avec Mimus, vous pouvez exécuter des charges de travail simulées pour évaluer la capacité optimale de l'architecture, capacité généralement fonction du nombre d'utilisateurs simultanés.

Le code source de Mimus est disponible à l'adresse https://github.com/GoogleCloudPlatform/mimus-game-simulator.

Présentation de l'architecture Mimus

Simulation d'un client Mimus dans un serveur Mimus

Dans les jeux MASS, la vitesse à laquelle le client du jeu génère des requêtes de base de données peut être contrôlée par le développeur du jeu. Celui-ci peut demander au joueur de regarder des animations et d'interagir avec le client du jeu pour pouvoir continuer. Mimus simule ces stratégies de limitation de débit avec des appels sleep(). De cette façon, Mimus simule une approximation raisonnable de la charge de base de données par client en exécutant autant de processus que de joueurs simulés. Ceci est efficacement orchestré à l'aide d'un pod client/serveur Mimus en conteneur, dans un cluster Kubernetes, qui envoie des requêtes à la base de données.

Le client du jeu Mimus simule la communication avec le serveur de backend en utilisant une boucle continue qui appelle directement les procédures du serveur Mimus, et en choisissant les appels de fonction selon l'état du joueur et de son inventaire.

Les actions de jeu simulées par Mimus comprennent :

  • la réalisation d'un tour du jeu ;
  • l'achat de monnaie ;
  • la dépense de monnaie ;
  • le nivellement ou l'évolution des unités.

Chacune de ces actions est implémentée en tant qu'interactions CRUD multiples avec les objets du joueur ou les objets unitaires, manipulés par le client via des appels au serveur Mimus. Le serveur Mimus effectue ces requêtes de base de données en utilisant l'API de base de données Mimus synchrone (bloquante). Cette API est un module Python importé par le serveur Mimus. Elle peut être configurée pour tester différentes implémentations de backend de base de données.

Communication entre l'API et le pool de nœuds de calcul de la base de données Mimus

Le schéma suivant représente la communication entre le serveur Mimus et le service de base de données.

Conception de communication de Mimus

L'API de base de données Mimus accepte des lots de requêtes de base de données et renvoie les résultats. Elle publie ces lots en tant que messages Cloud Pub/Sub, et attend que les résultats soient renvoyés via Redis. Avant d'envoyer un message, l'API de base de données valide toutes les valeurs qui seront écrites dans la base de données, et marque le message avec un ID de transaction unique. Le message est ensuite publié dans une rubrique Work dans Cloud Pub/Sub. Ensuite, l'API de base de données boucle, interrogeant l'existence de l'ID de transaction en tant que clé Redis. Les résultats dans la valeur de la clé sont ensuite récupérés par l'API de base de données et renvoyés au serveur Mimus, à partir duquel ils sont mis à la disposition du client Mimus.

Remarques relatives au choix de la communication

Mimus utilise Cloud Pub/Sub pour la communication de requêtes en attente, car les actions de l'utilisateur nécessitent une durabilité et une diffusion fiables. Mimus utilise Redis pour communiquer les résultats, où la durabilité et la fiabilité sont moins critiques. Si les résultats sont perdus en raison d'une erreur de l'application ou d'un échec de Redis, le client Mimus demande à nouveau les résultats finaux à la base de données. En utilisant les transactions d'une base de données relationnelle, vous avez la garantie que toutes les modifications demandées ont eu lieu, ou alors aucune d'entre elles. Mimus a rarement besoin de faire une seconde demande. Ce cas rare est considéré comme un compromis acceptable en échange de la simplicité et de la rapidité de récupération offertes par Redis. Pour que l'utilisation de Redis reste raisonnable, les résultats de la requête expirent trente secondes après la réponse de Redis.

Pool de nœuds de calcul de la base de données Mimus

Le pool de nœuds de calcul de la base de données Mimus contient plusieurs processus qui s'exécutent sur Kubernetes Engine. Chaque instance de conteneur en cours d'exécution interroge la rubrique Work de Cloud Pub/Sub dans une boucle sans fin à la recherche de nouveaux messages. Quand elle reçoit un message, elle exécute les requêtes dans le message en utilisant le module Python MySQLdb. Un seul message représente une transaction relationnelle et peut contenir plusieurs requêtes. Toutes les requêtes du message doivent être terminées avant d'être validées dans la base de données. Une fois les requêtes terminées (ou échouées), l'agent de base de données publie les résultats dans Redis sous l'ID de transaction reçu dans le message d'origine.

Base de données Mimus

La base de données relationnelle qui sauvegarde le service de base de données Mimus est une instance Cloud SQL pour MySQL deuxième génération. Lors de la création de l'instance, vous pouvez sélectionner des configurations de machine pouvant aller jusqu'à 32 cœurs et 208 Go de mémoire RAM, et des tailles de disque allant jusqu'à 10 To. En plus d'être compatibles avec les instances dupliquées, les instances Cloud SQL de deuxième génération sont configurées pour exécuter par défaut des sauvegardes régulières. Si vous devez encore affiner le réglage de MySQL, vous pouvez définir des indicateurs MySQL spécifiques sur l'instance Cloud SQL. Vous trouverez d'autres d'informations sur la configuration dans la documentation de Cloud SQL.

Conclusions du test de Cloud SQL avec Mimus

Type de machine Cloud SQL 2G Nombre suggéré d'utilisateurs simultanés
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

En utilisant l'atelier de test Mimus pour simuler 100 000 utilisateurs simultanés sur une instance Cloud SQL pour MySQL de deuxième génération, elle-même créée sur une instance Compute Engine n1-highmem-16, le temps de réponse de la requête est resté inférieur à 2 secondes pendant le test.

Si vous créez un jeu mobile MASS et que vous devez accepter des centaines de milliers de joueurs simultanés, un modèle de base de données orientée service basé sur Cloud SQL pour MySQL de deuxième génération peut fournir les performances requises. Lorsque votre jeu gagne en popularité, vous pouvez introduire des instances Cloud SQL supplémentaires, partagées ou dupliquées, ainsi qu'une stratégie de mise en cache Redis ou Memcached au niveau du service de base de données pour maintenir les performances à des niveaux acceptables.

Pour les jeux dont le nombre d'utilisateurs simultanés projetés est moins élevé, vous pouvez utiliser un type de machine plus petit pour réduire les coûts.

Pour les jeux dont le nombre d'utilisateurs simultanés projeté est de plusieurs millions, envisagez d'utiliser une base de données NoSQL (Google Cloud Datastore ou Google Cloud Bigtable, par exemple) dotée d'une forte évolutivité et de performances élevées.

Étapes suivantes

  • Testez par vous-même d'autres fonctionnalités de Google Cloud Platform. Découvrez nos tutoriels.
Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…