Q&R sur le Server Meshing et le streaming persistant

Traduction: Hotaru, odysseus1992
Relecture: Hotaru, odysseus1992, Yoko
Intégration: odysseus1992

Lors de la CitizenCon 2951, nous avons plongé dans les technologies innovantes que sont le Server Meshing et le streaming persistant, avec Paul Reindell (directeur de l’ingénierie, technologie en ligne) et Benoît Beauséjour (directeur de la technologie chez Turbulent). Après le panel, nous avons constaté que de nombreuses personnes avaient des questions à poser à nos panélistes, et nous voulons nous assurer qu’elles reçoivent une réponse. Nous vous invitons à lire la suite de notre entretien avec Paul, Benoît, Roger Godfrey (producteur principal) et Clive Johnson (programmeur réseau principal).

Quand verrons-nous le streaming persistant et le Server Meshing dans l’Univers persistant ?

Notre objectif actuel est de publier le streaming persistant et la première version de la couche de réplication idéalement entre le premier et le deuxième trimestre de l’année prochaine (ndt : ce Q&R a été publié en novembre 2021). Nous poursuivrons ensuite avec la première version d’un Server Meshing statique, sauf complications techniques imprévues, entre le troisième et le quatrième trimestre de l’année prochaine.

Quel est l’état actuel de la technologie de Server Meshing et quels sont les principaux problèmes qui l’entravent ?

La plupart des gens, lorsqu’ils parlent de Server Meshing, pensent généralement à l’étape finale de cette technologie, qui consiste à coordonner les serveurs. La vérité est qu’avant cette étape finale, une très longue chaîne d’exigences préalables et de changements technologiques fondamentaux doivent être apportés au moteur du jeu. Dans cette optique, je vais essayer de répondre à cette question en prenant en compte tous les éléments.

La réponse courte est qu’elle est en fait très avancée.

Maintenant, la version longue. La voie vers le Server Meshing a commencé en 2017/2018 :

Object Container Streaming

Pour que le Server Meshing fonctionne, nous avions d’abord besoin d’une technologie qui nous permette de lier/délier dynamiquement des entités via le système de streaming, car ce n’est pas quelque chose que le moteur prenait en charge à nos débuts. Ainsi, lorsque nous avons publié l’Object Container Streaming côté client (OCS) en 2018, nous avons également réalisé la toute première étape vers le Server Meshing !

Une fois ce premier jalon franchi, la technologie qui nous permet de lier/délier dynamiquement des entités sur le client devait également être activée sur le serveur (car, à terme, les nœuds de serveur du maillage devront faire apparaître/disparaître des entités de manière dynamique). Cette technologie est appelée “Object Container Streaming côté serveur” (S-OCS), et la première version du S-OCS a été publiée fin 2019. Il s’agissait de la deuxième grande étape vers le Server Meshing.

Autorité des entités et transfert d’autorité

Bien que nous disposions de la technologie nous permettant de générer dynamiquement des entités sur le serveur, il n’y a toujours qu’un seul serveur qui “possède” toutes les entités simulées. Dans un maillage où plusieurs nœuds de serveur partagent la simulation, nous avions besoin du concept “d’autorité des entités”. Cela signifie qu’une entité donnée n’est plus la propriété d’un seul serveur de jeu dédié, mais qu’il existe plusieurs nœuds de serveur dans le maillage. Donc, un nœud de serveur qui contrôle l’entité, et plusieurs autres nœuds de serveur qui ont une vue client de cette entité. Cette autorité doit également pouvoir être transférée entre les nœuds de serveur. Une bonne partie du temps de développement a été consacrée au concept “d’autorité des entités” et de “transfert d’autorité” au cours du premier semestre 2020. C’est la première fois que l’ensemble de l’entreprise a dû travailler sur le Server Meshing, car une grande partie du code de jeu a dû être modifiée pour fonctionner avec le nouveau concept d’autorité d’entités. À la fin de l’année 2020, la plupart du code (du jeu) a été modifié pour prendre en charge le concept, donc une autre grande étape a été franchie, pourtant il n’y a pas encore de réel maillage.

Couche de réplication et streaming persistant

L’étape suivante consistait à déplacer la réplication des entités dans un endroit central où nous pouvons contrôler la logique de streaming et de liaison au réseau. Cela nous permet ensuite de répliquer l’état du réseau sur plusieurs nœuds de serveur. Pour ce faire, nous avons dû déplacer la logique de streaming et de réplication du serveur dédié vers la couche de “réplication”, qui héberge désormais le code de réplication du réseau et de streaming des entités.

En même temps, nous avons implémenté le streaming persistant, qui permet à la couche de réplication de faire persister l’état des entités dans une base de données orientée graphe qui stocke l’état de chaque entité répliquée du réseau. L’année 2021 a été consacrée au travail sur la couche de réplication et EntityGraph, qui nous permet de contrôler le streaming et la réplication des entités à partir d’un processus distinct (séparé du serveur de jeu dédié traditionnel). Ce travail est presque terminé et se trouve dans sa phase finale.

Server Meshing statique et dynamique

Cependant, ce n’est pas encore un “maillage”. Le travail sur le maillage proprement dit a commencé et il nous faudra une bonne partie de l’année prochaine pour le terminer, et toutes les conditions préalables que j’ai décrites ci-dessus étaient nécessaires pour en arriver à ce point. La première version de cette technologie sera un Server Meshing statique et constitue le prochain grand pas en avant. Cependant, ce ne sera pas non plus la dernière ! Avec le maillage statique, nous disposerons de la première version d’un véritable maillage mais, comme le nom “statique” l’indique, la capacité à faire évoluer ce maillage est très limitée.

Avant de pouvoir considérer cette fonctionnalité comme achevée, nous devrons franchir une autre étape importante, que nous appelons “maillage dynamique”. Cette étape nous permettra de mailler dynamiquement les nœuds de serveur entre eux, puis de faire évoluer le maillage dynamiquement en fonction de la demande. Une grande partie du travail sur cette partie se fait en parallèle. Par exemple, le “gestionnaire de flotte” qui contrôle la demande dynamique du maillage est déjà en cours de développement, ainsi que les critères de matchmaking qui viennent avec la nouvelle inclusion des “shards”.

En parallèle, de nombreuses équipes doivent également œuvrer à l’adaptation du code du jeu déjà existant pour que celui-ci fonctionne pleinement avec une maille de serveurs (et surtout trouver tous les cas limites qui ne feront surface que lorsque nous aurons un véritable maillage). Bien que le travail sur l’autorité des entités ait été achevé en 2020, celle-ci n’est actuellement transférée qu’entre le client et un seul serveur, de sorte que certains codes peuvent nécessiter des ajustements supplémentaires.

Comment envisagez-vous de gérer un grand vaisseau, par exemple un Javelin ? S’agira-t-il d’une ressource dédiée avec des vaisseaux autour ?

Avec le Server Meshing dynamique, il est possible que de grands vaisseaux tels que le Javelin aient leur propre serveur dédié pour exécuter la simulation faisant autorité pour ce vaisseau et tout ce qu’il contient. Cependant, nous essayons d’éviter d’avoir des règles inflexibles sur la façon dont les entités sont assignées aux ressources de traitement, donc ce ne sera pas toujours le cas. C’est une question d’efficacité, tant en termes de vitesse de traitement que de coûts liés aux serveurs. Si nous avions une règle stricte selon laquelle chaque Javelin et tout ce qu’il contient reçoit son propre serveur, cela ne serait pas très rentable lorsqu’un Javelin ne compte qu’une poignée de joueurs. La même règle ne serait pas non plus efficace en termes de vitesse de traitement des serveurs s’il y avait des centaines de joueurs entassés dans le même Javelin, car la règle nous empêcherait de répartir la charge de traitement sur plusieurs serveurs.

Le Server Meshing dynamique sera un peu différent dans la mesure où il réévaluera en permanence la meilleure façon de répartir la simulation, afin de trouver le point idéal pour qu’aucun serveur ne soit surchargé ou sous-utilisé. Au fur et à mesure que les joueurs se déplacent dans le ‘verse, la distribution idéale des ressources de traitement changera. Pour réagir à ces changements, nous devrons être en mesure de transférer l’autorité sur les entités d’un serveur à un autre, ainsi que de mettre en ligne de nouveaux serveurs et de fermer les anciens. Cela nous permettra de déplacer la charge de traitement d’un serveur qui risque d’être surchargé vers un serveur qui est actuellement sous-utilisé. Si aucun des serveurs existants ne dispose d’une capacité de réserve suffisante pour faire face à une augmentation de la charge, nous pouvons simplement louer d’autres serveurs auprès de notre fournisseur de plateformes cloud.  Et lorsque la charge de certains serveurs n’est plus suffisante pour les rendre rentables, certains d’entre eux peuvent transférer leurs parties de la simulation sur les autres et nous pouvons fermer ceux dont nous n’avons plus besoin.

Combien de joueurs pourront se voir dans un même espace ? Quel est le maximum que vous prévoyez ?

Il est difficile de répondre à cette question, et la meilleure réponse que nous puissions donner pour l’instant est que cela dépend.

En supposant que la question porte sur la limite du nombre de joueurs pouvant se voir du point de vue d’un client, elle est principalement dictée par le client du jeu. Cela est dû à la simulation côté client, comme la physique et le code du jeu, ainsi qu’au coût du rendu.

En outre, cela dépend aussi fortement du scénario ; il est moins coûteux de simuler et de rendre sur le client 100 joueurs en combat FPS que 100 joueurs se battant dans des vaisseaux spatiaux monoplaces et se tirant des missiles et des lasers dessus.

L’équipe graphique travaille activement sur Vulkan, qui nous permettra d’augmenter les “draw calls” et devrait améliorer le nombre de joueurs/de vaisseaux que nous pouvons rendre en même temps, tandis que l’équipe moteur se concentre sur les optimisations du code pour augmenter le nombre d’objets en jeu que nous pouvons simuler en même temps.

Notre objectif est d’augmenter le nombre de joueurs et nous espérons pouvoir supporter des scénarios où 100 joueurs peuvent se voir à des fréquences d’images raisonnables. Cependant, lorsque nous commencerons à adapter nos shards pour supporter un nombre plus élevé de joueurs, la probabilité que chaque joueur d’un shard puisse se rendre au même endroit physique et se voir sans problème de performance diminuera.

C’est là que nous devrons commencer à implémenter des mécanismes de jeu qui empêcheront ces scénarios de se produire trop fréquemment.

La limite absolue est difficile à prévoir tant que la nouvelle technologie n’est pas en ligne et que nous ne pouvons pas commencer à évaluer les performances.

Harroway

Si j’établis une base sur un astre, celle-ci sera-t-elle dupliquée sur les autres shards où je ne me trouve pas ?

L’équipe chargée de la technologie planétaire prévoit d’implémenter la construction de base en tenant compte des shards des serveurs. Revendiquer une terre pour votre base sécurisera cet espace sur tous les shards, et nous prévoyons de répliquer votre base sur tous les shards.

Toutefois, un seul shard possèdera une version “active” de la base, les autres shards affichant une version “à accès limité/visible seulement” de ladite base. Par exemple, une base se verra attribuer l’accès complet ainsi que la possibilité d’être étendue au sein du shard où le propriétaire joue à un instant t, tandis que sur tous les autres shards, cette base apparaîtra avec des portes verrouillées et sous un état immuable. Le concept n’est pas complètement bien défini et pourrait toutefois changer.

Le véritable objectif est-il d’obtenir un seul et même shard pour tous les joueurs ?

C’est notre projet, cependant donner une réponse définitive n’est à l’heure actuelle pas possible.

Nous commencerons par de nombreux shards de petite envergure par région et réduirons progressivement leur nombre. Le premier grand objectif sera de réduire ce dernier pour n’en avoir plus qu’un par région. Pour en arriver là, notre plan consiste à progressivement augmenter le nombre de joueurs par shard et d’améliorer constamment les technologies du côté backend comme du côté client pour supporter de plus en plus de joueurs.

Il n’est pas uniquement question de changement de technologies pour atteindre ce but – un nouveau game design et de nouvelles mécaniques de jeux sont également requises. Sans les mécaniques pour empêcher chaque joueur d’aller au même endroit, il serait difficile d’avoir un shard gigantesque, surtout côté client. Par exemple, il pourrait y avoir une mécanique pour fermer temporairement des points de saut bondés, ou créer de nouvelles couches pour certains lieux.

Bien que le backend soit conçu pour s’étendre sur plusieurs machines, le client de jeu tourne sur une seule machine et est limité en termes d’exploitation de cœurs de CPU/GPU comme de mémoire.

Ce n’est qu’une fois que nous franchirons ces obstacles, et que nous atteindrons les méga-shards régionaux, que nous serons en mesure de nous attaquer au dernier boss : la fusion des shards régionaux en un méga shard global.

Ce défi s’accompagne de ses propres contraintes, dans la mesure où la localisation joue un grand rôle dans l’expérience de jeu. Par exemple, la latence entre les services d’un même datacenter est bien plus faible que celle entre des services hébergés par deux datacenters éloignés l’un de l’autre. Et bien que nous ayons conçu le backend pour supporter un shard global, c’est un défi opérationnel de déployer le backend de façon à ce qu’aucun groupe de joueurs ne soit favorisé au détriment d’un autre.

L’économie de l’univers sera-t-elle indépendante d’un shard à l’autre ou universelle ?

L’économie sera globale et répliquée dans chaque shard.

Par exemple, intéressons-nous aux boutiques. Bien que chaque boutique possède un inventaire local (les objets qui sont en vitrine), les boutiques se ravitaillent dans un inventaire global partagé par tous les shards. Si un grand nombre de joueurs commence à acheter un même pistolet dans la boutique d’armes de Port Olisar, son prix augmentera dans cette boutique sur tous les shards. Au final, le stock de ce pistolet sera épuisé, par conséquent les boutiques de tous les shards ne pourront plus se ravitailler avec ce modèle.

Qu’est-ce qui empêchera de larges organisations de joueurs “bleus” ou “rouges” d’occuper entièrement un shard ? Une dynamique sociale impliquerait une forte concentration d’individus ayant des amis et appartenant à des organisations partageant les mêmes intérêts. Y aura-t-il une solution pour assurer un mélange hétérogène de joueurs bons, mauvais, et entre les deux ?

Les joueurs ne seront pas assignés aux shards de façon permanente puisque le système de matchmaking attribue un nouveau shard pour la région sélectionnée à chaque connexion. Dès le départ, cela entraînera une distribution normale, puisque les joueurs commenceront en parallèle dans de nombreux petits shards.

Quand nous procéderons à l’extension de nos shards (et donc que nous diminuerons le nombre de shards parallèles), cette question aura plus de pertinence. Nous prévoyons de régler ce problème avec notre nouveau système de matchmaking.

Ce nouveau système de matchmaking actuellement en développement en parallèle du Server Meshing nous permet de réunir les joueurs sur des shards en nous basant sur différents paramètres d’entrée. Ceux-ci sont utilisés pour placer des joueurs avec leurs amis, ou bien là où ils ont perdu la plupart de leurs objets dans le monde ouvert. Cependant, ce système nous permet d’utiliser davantage de paramètres avancés, comme la réputation et d’autres statistiques de joueurs cachées que nous relevons.

Ce système nous garantira que chaque shard soit habité par une population plus ou moins hétéroclite de joueurs. Par exemple, nous pourrons nous assurer de ne pas remplir par inadvertance un shard avec uniquement des joueurs respectueux de la loi, ce qui ne serait pas très amusant dans la mesure où une partie de leurs activités concerne la traque de joueurs criminels.

Notre personnage et notre vaisseau seront-ils toujours présents en jeu après notre déconnexion ? En d’autres termes, si je me déconnecte depuis la couchette de mon vaisseau sur la surface d’une planète, mon vaisseau s’y trouvera-t-il toujours au risque que des gens parviennent à s’infiltrer à l’intérieur ou le détruisent ?

Quand une entité est “sortie” dans un shard (elle existe physiquement au sein de ce dernier), elle existe de façon permanente dans le shard jusqu’à ce qu’un joueur la “range” dans un inventaire. Cela peut être effectué en ramassant un pistolet et en le plaçant dans votre sac à dos, ou en posant un vaisseau sur un pad d’atterrissage, qui rangera le vaisseau dans un inventaire propre au pad. Une fois qu’une entité se trouve dans un inventaire, elle est stockée dans une base de données globale et peut être sortie dans n’importe quel shard. Cela permet aux joueurs de déplacer des objets d’un shard à l’autre.

Nous prévoyons également de créer une mécanique appelée “Ranger/sortir un objet héros[1]”. Cela consistera à prendre n’importe quel “objet héros” appartenant à un joueur pour le ranger automatiquement dans un inventaire de transition de shard propre au joueur. Le rangement automatique se fait habituellement quand aucun autre joueur ne se trouve dans les parages et que l’entité disparaît. Les objets présents dans cet inventaire de transition de shard suivront un joueur automatiquement, donc quand celui-ci se connecte dans un autre shard, nous prendrons les entités et les sortirons dans le nouveau shard à l’endroit où le joueur les a laissés.

Lorsque vous posez votre vaisseau sur une lune et que vous vous déconnectez, le vaisseau disparaîtra et sera automatiquement rangé si aucun autre joueur ne se trouve aux alentours à ce moment-là. Ensuite, quand vous vous connecterez dans un autre shard, votre vaisseau y sera placé. Si, pour quelque raison que ce soit, le vaisseau restait plus longtemps dans l’ancien shard et se voyait détruire alors que vous étiez déconnecté, vous pourriez vous réveiller dans un lit médicalisé.

À quel point le nouveau contenu dépend-t-il désormais du Server Meshing ?

Bien que le Server Meshing nous permet de commencer à augmenter le nombre de joueurs qui peuvent jouer ensemble dans Star Citizen, il nous débloquera également la possibilité d’ajouter de nouvelles expériences liées au contenu. Actuellement, nous nous concentrons sur cette exploitation pour ajouter de nouveaux systèmes stellaires. Le Server Meshing est l’une des technologies centrales pour faire fonctionner les points de saut en jeu en permettant aux systèmes stellaires d’apparaître et disparaître de la mémoire sans recourir à un écran de chargement. Les joueurs en seront témoins l’année prochaine quand la première itération du Server Meshing sortira sur les serveurs live à l’occasion de l’introduction du système Pyro.

À mesure que cette technologie s’affinera et que nous nous éloignerons d’un Server Meshing statique pour aller vers un Server Meshing dynamique, les concepteurs pourront s’en servir pour avoir des zones plus grandes et plus intéressantes (comme de plus grandes colonies ou des intérieurs de gros vaisseaux) densément peuplés d’IA et de joueurs. Le Server Meshing pourrait ouvrir la voie à des expériences de gameplays auxquels nos concepteurs n’ont pas encore pensé !

À quelle amélioration des performances pouvons-nous nous attendre ?

Le plus gros gain de performance se fera côté serveurs. À l’heure actuelle, notre performance serveur est assez limitée par le grand nombre d’entités que nous devons simuler sur un seul serveur. Cela occasionne un framerate bas et une dégradation de l’état des serveurs, forçant le client à subir du lag réseau/du “rubber banding” et d’autres soucis de désynchronisation. Une fois que nous aurons au minimum le Server Meshing statique, nous nous attendons à avoir un framerate serveur considérablement plus élevé, occasionnant de surcroît moins de problèmes.

Du côté des FPS du client, le Server Meshing n’a que peu d’impact. Le client n’affiche d’ores et déjà que les entités à portée de vue. Il pourrait y avoir de légères améliorations, puisque nous pourrons étendre la portée d’affichage du client car, actuellement, certains objets ont une portée d’affichage limitée pour certaines fonctionnalités telles que le radar ou les missiles pour qu’ils fonctionnent correctement. Avec le Server Meshing, nous pouvons démultiplier le rayon d’affichage du client et du serveur. Cependant, ces améliorations seront minimes côté client. Toutefois, un meilleur taux de rafraîchissement côté serveur améliorera l’expérience globale dans le sens ou le lag réseau sera considérablement réduit.

Je sais qu’il n’y a peut-être pas de réponse à cette question, mais à la sortie du Server Meshing, de combien de shards pensez-vous avoir besoin ? Dix, cent, mille, plus ? On sait qu’abandonner le système de serveurs de jeu dédiés revient à avoir plus de joueurs par zone de jeu, nous ne savons pas combien vous en prévoyez.

La réponse courte est que nous ne pouvons pas avancer de nombre.

Le concept de shard est la composante “flexible” de l’architecture du maillage, et nous ne pourrons donner le nombre de shards nécessaires qu’une fois que tous les rouages seront en place, ce que nous prévoyons d’atteindre progressivement.

Avec la première version du streaming persistant (et non du maillage), nous voulons commencer par reproduire le fonctionnement que vous pouvez trouvez actuellement en ayant un shard par instance de serveur et un “réplicant” (surnommé “hybride”). La seule différence c’est que toutes les entités de ce shards resteront persistantes. Cela nous permet de nous préparer au pire scénario en ayant un très grand nombre de shards persistants et de “réplicants” pour tester les mécaniques de création/seed, la simulation avec des joueurs actifs, et de ralentir le cycle de création et de suppression. Nous voulons que la création et la suppression de shards dans cette première phase soient optimales, rapides et sans coûts supplémentaires.

Cette approche présente plusieurs avantages, dans la mesure où nous pouvons tester la persistance des shards plus tôt et, surtout, que nous pouvons relever des données actives sur de nombreux shards.

Quelques exemples (liste non exhaustive !) :

  • combien d’entités restent dans un shard persistant avec le temps (taux de croissance du shard) ;
  • le taille du graphe global (taux de croissance global) ;
  • combien de joueurs une seule base de données de shard peut gérer (utilisation joueur) ;
  • l’effet de différentes mécaniques de jeu sur les mises à jour des entités dans la base de données du shard (effets du gameplay) ;
  • profils de performance des files d’attente d’écriture, temps de requête moyens des clusters de bases de données de shards (statistiques de base de données de shard) ;
  • profils de performance des files d’attente d’écriture, temps de requête moyens des clusters de bases de données globales (statistiques de base de données globale) ;
  • efficacité du découpage en shards de la base de données (un autre niveau de création de shards !) du graphe.

Bien que nous ayons de bonnes estimations et des mesures internes pour ces informations, rien ne remplace de vrais joueurs qui génèrent une charge représentative sur le système.

Quand les autres composantes du maillage entreront en jeu, principalement pour le maillage statique, nous prévoyons de réduire progressivement le nombre de shards, en rassemblant les joueurs dans des shards de plus en plus gros jusqu’à ce que nous soyons satisfaits des performances des “réplicants”, des serveurs de jeu dédié et du graphe d’entité. Bien sûr, le maillage statique souffrira de problèmes de fusion et nous ne serons en mesure de passer à des shards plus grands qu’une fois le maillage dynamique en place.

À terme, avec le maillage dynamique, nous avons pour objectif de supporter de très grands shards.

Un objet aussi petit qu’une balle peut-il voyager à travers différents shards ?

Pour faire court : non.

Voyez les shards comme une instance complètement isolée de l’univers simulé, un peu comme ce que nous proposons actuellement avec des instances isolées par serveur dédié. Pour qu’un objet soit transféré entre plusieurs instances, ces objets doivent être rangés dans un inventaire avant d’être sortis dans un autre shard. Par exemple, si un joueur ramasse une arme dans un shard et la place dans son sac à dos. Ensuite, lorsque ce joueur se connecte dans un autre shard, le joueur peut sortir l’arme de son sac à dos, pour la sortir dans le nouveau shard.

Au sein d’un shard, une entité telle qu’un missile pourra voyager à travers de multiples nœuds de serveur si ceux-ci contiennent le missile dans la zone d’affichage du serveur. Un seul nœud de serveur contrôlera (décidera pour) ce missile, tandis que les autres nœuds ne verront qu’un affichage client de ce même missile.

Les balles apparaissent côté client. Donc, une unique version d’une balle apparaît sur chaque client et nœud de serveur, voilà pourquoi j’ai utilisé ci-dessus l’exemple d’une entité répliquée sur le réseau telle qu’un missile.

Quand vous parlez de différentes régions du monde, prévoyez-vous d’héberger quatre fermes de serveurs pour des zones comme les États-Unis, l’Union Européenne, la Chine et l’Océanie ? Ou prévoyez-vous d’avoir un “univers global unique” ? Si oui, comment comptez-vous gérer l’équilibrage des joueurs avec des variations de latences extrêmes ?

Nous prévoyons toujours de conserver une distribution régionale des services sensibles de réseau. Lors du déploiement initial du streaming persistant, la base de données globale sera véritablement globale. Les shards eux-mêmes seront distribués de façon régionale, donc un client du jeu se connectant à la région européenne sera préférentiellement associé à un shard européen. Avec la croissance des shards (en nombre de joueurs comme d’entités), nous prévoyons de revoir ce modèle et d’introduire au passage des services au niveau régional pour s’occuper des données plus proches de la région. 

Obliterate quantum matrix engines

Je vis en Europe de l’Est. Après avoir lancé le Server Meshing, serai-je en mesure de jouer avec des amis américains ?

Nous ne prévoyons pas de limiter les shards et les régions qu’un joueur peut choisir.

Un joueur sera libre de choisir n’importe quelle région où jouer et, au sein de cette région, nous permettront une sélection limitée de shard. Par exemple, le shard où se trouve vos amis ou celui où vous avez joué en dernier.

Puisque toutes les données de joueurs sont stockées dans la base de données globale, les joueurs peuvent passer d’un shard à l’autre de la même façon qu’ils peuvent changer d’instance aujourd’hui. Les objets qui sont stockés seront transférés avec le joueur et seront toujours accessibles quel que soit le shard.

Mort d’une couche de réplication : que subiront les joueurs lorsqu’une couche de réplication est coupée/“meurt” ? Nous savons que le graphe d’entité collectera les informations envoyées et les retransmettra dans une couche de réplication, mais retournerons-nous au menu principal si cette couche disparaît comme lorsqu’un noeud de serveur est retiré, ou aurons-nous une sorte d’écran de chargement qui nous placera automatiquement dans une nouvelle couche ?

Pour répondre correctement, je dois d’abord fournir plus de détails sur ce à quoi notre architecture finale ressemblera. À terme, la couche de réplication ne correspondra pas à un seul nœud de serveur. Au lieu de ça, il s’agira d’instances multiples d’une suite de microservices appelés “Replicant”, “Atlas” et “Scribe”. L’un des avantages est que la couche de réplication sera elle-même capable de s’adapter. Un autre avantage, plus en lien avec la question, est que même si un seul nœud/une seule instance dans la couche de réplication tombe en panne, il y a très peu de chances que toute la couche de réplication s’interrompe. Du point de vue d’un client, les noeuds “Replicant” sont l’élément le plus important puisque ce sont eux qui vont gérer le streaming d’entités en réseau ainsi que la réplication d’états entre les clients et le jeu. Le “réplicant” est conçu pour exécuter aucune logique de jeu et, d’ailleurs, il n’exécutera que très peu de code ; pas d’animation, pas de physique, simplement du code réseau. Étant conçu sur un “codebase” aussi restreint, cela devrait globalement réduire le nombre de bugs. Donc après quelques plâtres essuyés au démarrage, nous pensons que les “réplicants” seront assez stables. Il est également important de noter qu’à tout moment, un client peut être servi par plusieurs “réplicants” (mais ces derniers devront également servir d’autres clients en parallèle). La dernière pièce du puzzle est la couche “Gateway”. Ce service n’est là que pour diriger les paquets entre les clients et les nombreux “réplicants” auxquels ils s’adressent. Il utilisera un “codebase” encore plus restreint que celui d’un “réplicant” donc le risque qu’il crashe est encore plus faible.

Donc qu’arrivera-t-il à un client si l’un des “réplicants” auxquels il fait appel crashe subitement ?

Le client restera connecté au shard mais toute ou partie de la simulation se figera temporairement. La couche de réplication démarrera un nouveau nœud de réplication pour remplacer celui qui a crashé et reprendra l’état de l’entité perdue de la persistance via EntityGraph. Les gateways du client et les nœuds de serveurs de jeu dédiés qui étaient connectés à l’ancien “réplicant” ré-établiront une connexion avec le nouveau. Une fois que tout est reconnecté, le jeu reprendra son cours pour les clients concernés. À ce stade le client peut souffrir de disparition/téléportation d’entités. Nous espérons que tout ce processus prendra moins d’une minute.

Qu’arrivera-t-il à un client si la “Gateway” le supportant crashe subitement ?

Le service “Gateway” ne supporte aucun état de jeu et aura sa propre forme de récupération après un crash. Puisqu’il s’agit d’un service bien plus simple que celui du “réplicant”, le temps de récupération devrait être beaucoup plus court, de l’ordre de quelques secondes. Pendant que la récupération a lieu, le client sera temporairement figé puis subira quelques disparitions/téléportations.

Quid du service “Hybrid” ?

Au cours de leur présentation lors de la CitizenCon sur le streaming persistant et le Server Meshing, Paul et Benoît ont évoqué la couche de réplication en parlant de service “Hybrid”. Ce service, comme son nom l’indique, est un hybride entre les services “Replicant”, “Atlas”, “Scribe” et “Gateway” que j’ai mentionnés plus haut (mais pas EntityGraph), mais également d’une poignée d’autres services pas encore mentionnés. Nous avons choisi de développer cela en premier avant de séparer les services le composant puisque cela réduit le nombre de pièces amovibles avec lesquelles nous essayons de composer en même temps. Cela nous permet également de nous focaliser sur la mise à l’épreuve de tous les grands concepts plutôt que de simplement nous contenter de faire communiquer ces services entre eux. Dans cette première implémentation, la couche de réplication constituera un seul nœud de serveur “Hybrid”. Si ce dernier crashe, alors la situation sera similaire à ce que les clients subissent actuellement lorsqu’un serveur de jeu dédié crashe. Tous les clients seront renvoyés au menu du jeu avec la tristement célèbre erreur 30k. Une fois que le nœud “Hybrid” remplaçant a démarré, les clients seront en mesure de rejoindre le shard et de reprendre là où ils se sont arrêtés. Avec un peu de chance, nous pourrons l’implémenter de telle façon que le client reçoit une notification à l’écran indiquant que le shard est de nouveau disponible et l’appui d’une simple touche les reconnectera automatiquement dans le shard (comme cela se fait avec la récupération de crash du client).

Le panel a beaucoup parlé des nœuds qui ont l’autorité d’écriture au sein d’un shard, mais qu’en est-il de l’autorité d’écriture entre différents shards ? Maintenez-vous des bases de données séparées pour différents shards ou les états des objets de l’univers seront-ils finalement synchronisés entre shards même s’ils ont été laissés dans différents états ? (Par exemple, si une porte est laissée ouverte dans un shard et fermée dans un autre, l’un des shards finira-t-il par noter son état dans la base de données pour le mettre à jour dans l’autre shard ?)

De façon générale, chaque shard est sa propre copie de l’univers, et tout objet au sein dudit shard ne partagera pas son état avec un objet issu d’un autre shard puisque chaque shard possède sa propre base de données. D’un autre côté, nous avons bel et bien une base de données globale pour les données d’inventaire de joueur. Cette base de données est utilisée pour stocker n’importe quel objet dans l’inventaire d’un joueur, et les objets peuvent être transférés entre les shards s’ils sont d’abord rangés depuis un shard dans un inventaire et ensuite sortis dans un autre shard.

Certaines fonctionnalités, comme les avant-postes de joueurs ou les ressources de minage, intègrent un code spécial qui répliquera un état global dans tous les shards, donc un avant-poste peut exister dans plusieurs shards en parallèle et répliquer lentement (par rapport à la vitesse du jeu en temps réel) son état entre les shards. Il ne s’agit pas d’une réplication instantanée (une porte s’ouvrant/se refermant ne sera pas répliquée), cependant, un état persistant comme une porte verrouillée ou déverrouillée peut être répliquée entre plusieurs shards.

Cela fonctionne comme pour les ressources de minage : bien que chaque shard possède une version unique d’un rocher exploitable, la quantité globale sera répliquée entre les shards, donc quand les joueurs commencent à miner une certaine zone, la carte de ressource globale pour cette zone sera modifiée et le nombre de rochers exploitables à cet endroit sera modifié sur tous les shards.

Lorsqu’un groupe se déplace (voyage quantique ou autre) d’un endroit à un autre, et qu’un autre nœud de serveur de jeu dédié, qu’un autre lieu ou qu’une autre instance est complète, le maillage statique / tier zéro créera-t-il un autre nœud de serveur de jeu dédié préventivement ? Comment cela sera-t-il géré ?

Avec le Server Meshing statique, tout sera fixé à l’avance, y compris le nombre de nœuds de serveur par shard et quel serveur de jeu est responsable de la simulation de tel ou tel lieu. Cela signifie que si tout le monde dans le shard décide de se diriger au même endroit, ils seront au final tous simulés par le même nœud de serveur.

En fait, le pire scénario serait que tous les joueurs se décident de s’éparpiller dans tous les lieux assignés à un seul serveur de nœud. De cette façon, le pauvre serveur essaiera de gérer non seulement tous les joueurs mais également tous ses lieux. La solution évidente consiste à augmenter le nombre de serveurs par shard, pour que chaque shard ait à gérer moins de lieux. Cependant, parce qu’il est question de maillage statique et que tout est fixé à l’avance, avoir plus de nœuds de serveur par shard augmente également les coûts de fonctionnement. Mais nous devons bien commencer quelque part, donc l’idée pour la première version du Server Meshing statique est de commencer avec aussi peu de nœuds de serveur que possible tout en nous assurant que la technologie fonctionne. De toute évidence, cela posera problème si nous augmentons le nombre de joueurs par shard en dépassant le seuil actuel des 50 par serveur unique.

Donc ne vous attendez pas à voir le nombre de joueurs augmenter beaucoup avec la première version. Cela évite les problèmes tels qu’un seul nœud de serveur qui est déjà plein avant même que les joueurs ne s’y rendent puisque nous limiterons le nombre maximum de joueurs par shard en nous basant sur le pire scénario. Une fois que nous aurons mis en place ce système, nous examinerons les performances et les aspects économiques et verrons jusqu’où nous pourrons aller. Mais pour rendre de futures extensions économiquement viables, nous devrons chercher à rendre le Server Meshing dynamique aussi tôt que possible.

Compte tenu de l’énorme volume de données circulant entre les clients et les nœuds de serveur, et de la nécessité d’une latence extrêmement faible, pouvez-vous décrire ou préciser comment vous gérez cela ou quelles technologies vous utilisez pour accélérer les choses, ou plutôt pour les empêcher de ralentir ?

Les principaux facteurs qui influent actuellement sur la latence sont le “tick rate” des serveurs, le ping des clients, le “spawn” d’entités et la latence des services persistants.

Le “tick rate” du serveur a l’effet le plus important et est lié au nombre d’emplacements qu’un serveur du jeu simule. Le Server Meshing devrait y contribuer en réduisant le nombre d’emplacements que chaque serveur du jeu doit simuler. Moins d’emplacements signifie un nombre moyen d’entités par serveur beaucoup plus faible et les économies réalisées peuvent être réinvesties pour augmenter le nombre de joueurs par serveur.

Le ping du client est influencé par la distance qui le sépare du serveur. Nous constatons que de nombreux joueurs choisissent de jouer sur des régions situées sur des continents complètement différents. Une partie de notre code du jeu donne encore l’autorité au client, ce qui signifie que les joueurs ayant un ping élevé peuvent nuire à l’expérience de jeu de tous les autres. Il n’y a pas grand-chose que nous puissions faire à ce sujet à court terme, mais c’est un point que nous voulons améliorer une fois le Server Meshing opérationnel.

L’apparition lente d’entités peut entraîner une latence en retardant l’arrivée des entités sur les clients. Cela peut avoir des effets indésirables, tels que des lieux qui n’apparaissent complètement que quelques minutes après que le voyage quantique soit terminé, la chute à travers les étages après avoir réapparu dans un lieu, des vaisseaux qui mettent longtemps à apparaître sur les terminaux ASOP, la modification de l’équipement du joueur, etc. Les goulots d’étranglement se situent principalement au niveau du serveur. Premièrement, les entités ne sont pas répliquées sur les clients tant qu’elles n’ont pas fini d’apparaître sur le serveur. Deuxièmement, le serveur a une seule file d’attente de “spawn” qu’il doit traiter dans l’ordre. Troisièmement, plus un serveur a besoin de générer un grand nombre de lieux, plus il doit faire de “spawns”. Pour améliorer les choses, nous avons modifié le code de “spawn” du serveur pour utiliser des files d’attente de “spawns” parallèles. Le Server Meshing sera également utile, non seulement en diminuant la charge sur les files d’attente de “spawn” en réduisant le nombre d’emplacements qu’un serveur doit générer, mais aussi parce que la couche de réplication réplique les entités aux clients et aux serveurs simultanément, leur permettant le “spawn” en parallèle.

Nous utilisons toujours certains de nos anciens services persistants, adéquats tels qu’ils ont été conçus mais connus pour avoir des problèmes de performance et d’évolutivité en fonction de nos exigences.  Il peut en résulter de longues attentes lors de la récupération des données persistantes des services afin de savoir quoi faire apparaître, comme faire apparaître un vaisseau à partir d’un terminal ASOP, examiner un inventaire, changer l’équipement du joueur, etc. Puisque le streaming persistant complet et le Server Meshing vont tous deux augmenter considérablement la quantité de données que nous devons faire persister, nous savions que nous devions faire quelque chose à ce sujet. C’est pourquoi Benoît de Turbulent et son équipe ont complètement réinventé la façon dont nous allons faire persister les données sous la forme d’EntityGraph, qui est un service hautement évolutif construit au-dessus d’une base de données qui l’est tout autant et qui est optimisée pour exactement le type d’opérations de données que nous effectuons. En plus de cela, nous développons également la couche de réplication, qui agit comme un cache en mémoire hautement évolutif de l’état actuel de toutes les entités d’un shard, éliminant ainsi la nécessité de la majorité des requêtes que nous avons envoyées aux services persistants existants. Eh oui, il va y avoir des services hautement évolutifs du début à la fin !

Pour aider à réduire/éliminer toute latence supplémentaire que la couche de réplication pourrait introduire, nous la construisons de manière à ce qu’elle soit pilotée par des événements plutôt que par un “tick rate” comme un serveur de jeu traditionnel. Cela signifie que lorsque des paquets arrivent, elle les traite immédiatement et envoie la réponse et/ou transmet les informations aux clients et serveurs du jeu concernés. Une fois que le travail sur la version initiale de la couche de réplication sera terminé (le service “Hybride”), nous effectuerons une passe d’optimisation pour nous assurer qu’elle sera aussi réactive que possible. Et, bien qu’il s’agisse en fin de compte d’une décision à prendre par le département DevOps, nous les déploierons dans les mêmes centres de données que les serveurs du jeu eux-mêmes, de sorte que la latence du réseau due à l’étape supplémentaire entre la couche de réplication et le serveur du jeu devrait être inférieure à une milliseconde. Oh, et ai-je mentionné que la couche de réplication sera hautement évolutive ? Cela signifie que si nous détectons que la couche de réplication provoque des problèmes de latence dans certaines parties du ‘verse, nous pourrons la reconfigurer pour remédier au problème.

Clause de non-responsabilité

Les réponses reflètent fidèlement les intentions de développement au moment de la rédaction, mais l’entreprise et l’équipe de développement se réservent le droit d’adapter, d’améliorer ou de modifier les fonctionnalités et la conception des vaisseaux en réponses aux retours, aux tests, aux révisions de la conception ou à d’autres considérations visant à améliorer l’équilibre ou la qualité du jeu dans son ensemble.

PULSAR42 Association à but non lucratif de droit français régie par la loi du 1er juillet 1901, N° RNA : W923006718. SIRET 839 734 175 00012 - APE 9499Z

Design By June Lottin

This site is not endorsed by or affiliated with the Cloud Imperium or Roberts Space Industries group of companies. All game content and materials are copyright Cloud Imperium Rights LLC and Cloud Imperium Rights Ltd.. Star Citizen®, Squadron 42®, Roberts Space Industries®, and Cloud Imperium® are registered trademarks of Cloud Imperium Rights LLC. All rights reserved.