Comment l'équilibrage de charge est-il réalisé dans les MMO?


26

Je crois que c'est une exigence commune des MMO que le traitement pour un seul fragment ou domaine puisse être effectué sur plusieurs serveurs pour alléger la charge. Je suis curieux de savoir comment cela peut être fait tout en maintenant un monde cohérent unifié où tous les joueurs et tous les PNJ peuvent interagir.

Ma question est de savoir comment l'équilibrage de charge est-il réalisé dans les MMO?

Tous les liens, livres ou informations générales sur la façon d'améliorer mes connaissances à ce sujet sont également appréciés.

Réponses:


30

Essayez de garder cela aussi simple que possible et les interfaces bien définies et documentées. La maintenance et le débogage d'un système complexe en production se transforment facilement en enfer. Donc, s'il existe une approche simple et complexe, réfléchissez-y à deux fois avant de vous lancer dans l'approche complexe.

Définition des services

Je pense que la première étape consiste à identifier les services et leurs dépendances : contenu statique, authentification, chat local, canaux de chat global, canaux de chat régionaux, liste d'amis, guildes, sac / inventaire, salle des ventes, carte globale, monde, ...

Ensuite, pour chacun de ces services, il a été décidé si le client pouvait leur parler directement. Par exemple, il est assez facile de laisser le client parler directement avec les serveurs responsables des canaux de discussion globaux. Les serveurs mondiaux n'ont pas du tout besoin d'être impliqués dans les messages de chat. Le chat régional peut être implémenté de la même manière, mais les serveurs mondiaux doivent avertir les serveurs de chat lorsque les joueurs changent de région. Encore une fois, ils n'ont pas à se soucier des messages.

La troisième étape consiste à penser à l'équilibrage de charge au sein d'un service . Par exemple, les canaux de discussion mondiaux et régionaux peuvent être répartis sur plusieurs serveurs en fonction de leur nom. C'est probablement une bonne idée de ne pas coder en dur cette division dans le client, mais de fournir un service de recherche.

Serveurs du monde

La partie la plus difficile est généralement les serveurs mondiaux , donc je commence par une approche simple. C'est probablement une bonne idée de laisser le client parler directement au serveur responsable de la région dans laquelle il se trouve. Ainsi, lors de la connexion ou de la région traversée, le client doit être informé du serveur auquel se connecter.

L'approche simple consiste à diviser le monde en régions indépendantes . Avec des régions indépendantes, je veux dire qu'un joueur ne peut pas regarder d'une partie à une autre et que les monstres ne peuvent pas traverser de parties. Ces régions sont différentes des régions que les joueurs voient en fonction du paysage et de l'histoire du monde extérieur. Habituellement, la plupart des monstres sont dans des donjons et les joueurs ont tendance à accepter qu'ils doivent passer par une passerelle pour entrer dans un donjon. Surtout si ces donjons sont instanciés par groupe de joueurs. D'autres exemples sur le monde extérieur sont différents continents et vallées entourées de hautes montagnes.

Une approche mondiale continue devient très rapidement complexe, il est donc logique de bien la planifier: de quelles informations le client a-t-il besoin? Quelles informations les serveurs doivent-ils partager? Le joueur n'interagira principalement qu'avec les objets (y compris les monstres et les PNJ) de la même région. Vous pouvez tricher en plaçant des objets hors de portée de clic à partir de la bordure de la zone. Cela signifie que le client est principalement intéressé par la lecture seule des informations pour les zones voisines. Dans ces cas, les serveurs de zone n'ont rien à coordonner, sauf pour vérifier l'autorisation que le joueur est suffisamment proche pour se connecter à une zone voisine.

Cela ne laisse qu'un très petit nombre de cas difficiles dans lesquels des objets ou des actions doivent traverser une frontière de serveur. Ce qui est une bonne chose car ces cas tels que les flèches et les sorts sont critiques pour les performances. Il peut être judicieux de diviser le combat en attaque et en défense. Ainsi, le serveur d'un lanceur de sorts définira les paramètres d'attaque, y compris la position du lanceur de sorts. Le serveur du défenseur recevra le message de l'attaque et calculera l'impact. Le serveur de l'attaquant n'a pas besoin de connaître l'impact; le client l'apprendra en utilisant sa connexion en lecture seule.

Selon la complexité de votre modèle de lecteur, le transfert vers un autre serveur peut prendre quelques secondes (Second Life a un énorme problème avec cela). Le problème peut être atténué en préparant le transfert à l'avance lorsque le joueur se rapproche d'une frontière virtuelle. De sorte que la plupart des données du lecteur sont déjà mises en cache sur le serveur de destination lorsque le transfert réel se produit.

Sommaire

Divisez le problème en définissant différents services qui peuvent être répartis sur plusieurs serveurs avec peu de dépendances. Au cours de la prochaine étape, examinez la façon d'équilibrer la charge au sein des services critiques. Déléguez le travail d'équilibrage au client en lui demandant de se connecter directement aux serveurs concernés (les serveurs doivent évidemment vérifier les autorisations). Restez aussi simple que possible, documentez bien les responsabilités des différents services et serveurs, offrez l'option d'activer la sortie de débogage.

PS: Certaines de ces techniques peuvent être utilisées pour améliorer la fiabilité. Et vous devez garder cela à l'esprit car l'utilisation de nombreux serveurs implique un risque beaucoup plus élevé de rupture des choses; non seulement au niveau du logiciel mais également au niveau du matériel.


Mais vraiment, comment faites-vous cette communication interprocessus? quel type d'IPC doit être utilisé?
majidarif

10

Généralement, le monde est divisé en plusieurs petites régions. Chacune de ces régions est généralement un processus serveur indépendant (les serveurs mondiaux de WoW ou les nœuds Sol d'Eve) et peut s'exécuter sur n'importe quelle machine. Dans certains jeux, il y a des portes explicites entre les cartes (Eve, STO, Guild Wars) tandis que d'autres essaient de masquer cela davantage (WAR, Free Realms). Ceux qui optent pour l'approche plus transparente détectent généralement lorsque vous approchez de la frontière entre deux serveurs et que les deux processus négocient un transfert. Le meilleur endroit pour chercher probablement une description de cela est dans la façon dont les tours cellulaires effectuent les transferts de combinés mobiles. Si la charge d'une seule carte (Jita, Ironforge, Earth Space Dock) devient vraiment importante, vous pouvez parfois décharger des fonctions individuelles sur d'autres serveurs (AI, certaines parties de la gestion des joueurs), mais cela doit être intégré dès le départ ou nécessiterait une sérieuse rénovation. Il est presque toujours plus rentable d'acheter simplement un meilleur matériel à consacrer à ces quelques cartes.


9

Je crois que c'est une exigence commune des MMO que le traitement pour un seul fragment ou domaine puisse être effectué sur plusieurs serveurs pour alléger la charge. Je suis curieux de savoir comment cela peut être fait tout en maintenant un monde cohérent unifié où tous les joueurs et tous les PNJ peuvent interagir.

Ce n'est probablement pas aussi courant que vous le pensez; du moins, pas si vous pensez qu'un monde transparent est géré par plusieurs serveurs simultanément.

Sans compter les fragments totalement séparés, il y a 2 directions dans lesquelles vous pouvez diviser un jeu en ligne, qui pourrait être considéré comme "horizontal" et "vertical":

  • Divisez le jeu en plusieurs zones géographiques distinctes. Toutes les fonctionnalités d'une zone géographique donnée sont gérées par un seul serveur et il n'y a pas de réelle interaction entre elles. (Notez qu'il n'y a pas nécessairement une seule zone par serveur - un serveur peut gérer plusieurs zones simultanément et des zones peuvent peut-être être transférées entre les serveurs pour gérer la charge changeante.)
  • Divisez le jeu en plusieurs types de services - par exemple. connexion / autorisation, règles de jeu et physique, chat + enchères, persistance, etc. Chacun de ces services peut être géré par un serveur différent. La réponse de nhnb a énuméré d'autres services potentiels dans lesquels un développeur peut partitionner son jeu.

Évidemment, ces approches sont orthogonales et vous pouvez combiner les deux. En fait, il est presque obligatoire d'avoir un serveur de base de données séparé, très courant pour pousser la connexion / l'authentification sur une machine distincte du gameplay, et de plus en plus courant pour éliminer le chat et d'autres communications non critiques, quel que soit votre monde de jeu est divisé.

Mais dans l'ensemble, lorsqu'il y a partitionnement géographique, la plupart des jeux évitent de vous laisser interagir au-delà de ces frontières, car il est difficile de bien faire. Au lieu de cela, ils ont recours à d'autres façons de faire croire que vous êtes toujours dans le même fragment et sur le même serveur, alors qu'en réalité vous ne l'êtes pas. par exemple. - écrans de chargement ou autres animations qui masquent un changement de serveur lors de la transition entre les zones, ou d'un continent à l'autre. - des instances de donjon ou de raid séparées qui sont isolées de tout le monde. Celles-ci sont comme un fragment dans un fragment et peuvent facilement être exécutées sur un serveur distinct, ce qui facilite l'équilibrage de charge.

Je ne peux pas parler avec autorité sur WoW, mais je suppose qu'ils font presque tout ce qui précède: instanciation, zones géographiques distinctes qui ne peuvent pas interagir reliées par des portails d'une certaine sorte, serveurs d'arrière-plan et d'authentification séparés. J'ai entendu dire que les royaumes WoW ont entre 1000 et 10000 joueurs en ligne dans un royaume donné à la fois, ce qui est facilement gérable avec les schémas ci-dessus.

Mais, supposons que vous ayez un seul monde massif et que vous devez autoriser les joueurs un serveur à interagir avec les joueurs sur un serveur adjacent. Ceci est facile à faire en théorie - d'abord, les serveurs doivent coopérer pour partager les détails des objets le long des frontières (donc un objet sur un serveur peut avoir une représentation proxy sur un autre), puis changez simplement toute votre logique en passant des messages, avec si nécessaire, les messages sont acheminés d'un proxy vers la source faisant autorité. Les messages peuvent être transmis entre les serveurs ou au sein d'un serveur de manière assez transparente afin qu'une approche s'adapte à tous les systèmes.

Le problème ici est qu'une logique auparavant simple peut devenir très complexe lorsqu'elle est traduite en messages - par exemple. un échange à 2 joueurs qui peut se produire en toute sécurité et de manière atomique lorsque les deux joueurs sont sur un serveur devient un processus plus long lorsque des messages doivent être envoyés dans les deux sens, revérifiés à chaque envoi et des garanties mises en place pour garantir qu'un joueur ne peut pas exploiter l'autre en changeant de métier pendant qu'un message voyage. Vous ne pouvez même pas supposer que l'autre joueur existera toujours au moment où le message arrivera (car ils pourraient mourir, se déconnecter, etc.), donc le code devient très complexe. Et cela s'appliquera à presque tous les systèmes où 2 ou plusieurs entités peuvent interagir ou coopérer - commerce, combat, groupement, enchères, partage de butin, formation, etc.

Ces problèmes ne sont pas insurmontables, mais pour la plupart des jeux, ils sont trop difficiles à valoir lorsque vous pouvez partager la charge via les autres moyens et conserver toute votre logique de jeu sur un seul serveur. Donc, presque tous les jeux actuels suivent cette voie.


3

Il existe de nombreuses méthodes d'équilibrage de charge d'un serveur MMO, car il existe un large éventail de données à traiter. Je préfère la méthode d'arborescence de processus bin.

Un serveur global transmet les connexions utilisateur à un bac de processus qui peut gérer plusieurs utilisateurs à la fois. les bacs de processus effectuent tous les traitements complexes et ne répondent au serveur global qu'avec des données pertinentes au niveau mondial telles que le chat et le positionnement global. Cette méthode s'équilibre beaucoup mieux que les serveurs de régions, car les régions peuvent varier considérablement en population, tandis que le traitement global des utilisateurs est suffisamment varié pour s'équilibrer naturellement pour la plupart.

Effectuez simplement un équilibrage de charge de base via le serveur global. Ainsi, lorsqu'un bac de processus atteint une certaine utilisation de mémoire / processeur, vous démarrez un nouveau serveur de bac de processus.


Comment partager des données partagées entre des bacs de processus, par exemple un combat entre deux utilisateurs sur des bacs de processus différents. Comment assurez-vous l'ordre des événements? Pour qu'un joueur tué ne puisse plus attaquer, même si le bac qui le tue est plus lent que le bac qui attaque. Y a-t-il un risque que les frais généraux de répartition deviennent trop élevés sur le serveur global? Le modèle de proxy pour les connexions utilisateur peut entrer dans les limites du système d'exploitation sur la pile réseau.
Hendrik Brummermann

Ce modèle fonctionne plutôt bien dans les systèmes d'information où la plupart des transactions sont isolées. Je veux dire qu'ils ne fonctionnent généralement pas sur les mêmes données, et dans les rares cas, le verrouillage ou la restauration est utilisé. Mais dans les jeux où les combats incluent plusieurs joueurs et / ou créatures, et l'impact des attaques est influencé par les attributs de l'attaquant et du défenseur, cette approche peut être difficile.
Hendrik Brummermann

Vous pouvez soit opter pour la solution simple et considérer les interactions multi-utilisateurs comme pertinentes à l'échelle mondiale, soit créer une méthode simple pour que les corbeilles de processus se connaissent et communiquent. Chaque bin de processus devrait être capable de gérer environ dix mille utilisateurs à la fois, donc la communication d'état entre les utilisateurs ne devrait pas être trop problématique. La méthode de région est un peu plus facile, mais pas aussi équilibrée, et peut facilement être bloquée si trop d'utilisateurs entrent dans la même région. Dans un MMORPG avec une large base d'utilisateurs, l'équilibrage de la charge est également très important.
Stephen Belanger

J'adorerais connaître "une méthode simple" pour que 2 bacs de traitement puissent négocier un système comme le combat. Le problème n'est pas les communications de bas niveau mais les algorithmes de gameplay typiques deviennent très compliqués avec des participants distribués.
Kylotan

Dans mon implémentation, mon serveur global conserve une liste de tous les clients connectés et garde une trace du processus auquel ils sont connectés. Si un bin de processus doit accéder à un autre utilisateur, il vérifie d'abord sa propre liste d'utilisateurs. En cas d'échec, il vérifie la liste globale et identifie le bac de processus auquel l'autre utilisateur est connecté. Les corbeilles de processus se connectent ensuite directement pour partager les états utilisateur pendant le traitement unifié.
Stephen Belanger
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.