¿Cómo se logra el equilibrio de carga en los MMO?

26

Creo que es un requisito común de los MMO que el procesamiento para un solo fragmento o reino se pueda realizar en varios servidores para facilitar la carga. Tengo curiosidad por saber cómo se puede hacer esto mientras se mantiene un mundo consistente y unificado donde todos los jugadores y todos los NPC pueden interactuar.

Mi pregunta es ¿cómo se logra el equilibrio de carga en los MMO?

También se agradece cualquier enlace, libro o información general sobre cómo mejorar mi conocimiento sobre este tema.

CiscoIPPhone
fuente

Respuestas:

30

Intenta mantener esto lo más simple posible e interfaces bien definidas y documentadas. Mantener y depurar un sistema complejo en producción se convierte fácilmente en un infierno. Entonces, si hay un enfoque simple y complejo, piénselo dos veces antes de optar por el complejo.

Definiendo servicios

Creo que el primer paso es identificar los servicios y sus dependencias : Contenido estático, Autenticación, Chat local, Canales de chat globales, Canales de chat regionales, Lista de amigos, Gremios, Bolsa / Inventario, Casa de subastas, Mapa global, Mundo, ...

A continuación, para cada uno de estos servicios decidido si el cliente puede hablar con ellos directamente. Por ejemplo, es bastante fácil dejar que el cliente hable directamente con los servidores responsables de los canales de chat global. Los servidores mundiales no tienen que estar involucrados en los mensajes de chat. El chat regional se puede implementar de la misma manera, pero los servidores del mundo tienen que avisar a los servidores de chat cuando los jugadores cambian de región. Una vez más, no tienen que preocuparse por los mensajes.

El tercer paso es pensar en el equilibrio de carga dentro de un servicio . Por ejemplo, los canales de chat globales y regionales se pueden dividir en varios servidores según su nombre. Probablemente sea una buena idea no codificar esta división en el cliente, sino proporcionar un servicio de búsqueda.

Servidores mundiales

La parte más difícil suele ser los servidores del mundo , por lo que estoy comenzando con un enfoque simple. Probablemente sea una buena idea dejar que el cliente hable directamente con el servidor responsable de la región en la que se encuentra. Por lo tanto, al iniciar sesión o cruzar la región, el cliente debe saber a qué servidor conectarse.

El enfoque simple es dividir el mundo en regiones independientes . Con regiones independientes quiero decir que un jugador no puede mirar de una parte a otra y los monstruos no pueden cruzar partes. Esas regiones son diferentes de las regiones que el jugador ve en función del paisaje y la historia del mundo exterior. Por lo general, la mayoría de los monstruos están en mazmorras y los jugadores tienden a aceptar que tienen que atravesar una puerta de entrada para ingresar a una mazmorra. Especialmente si esas mazmorras se instancian por grupo de jugadores. Otros ejemplos en el mundo exterior son diferentes continentes y valles encerrados por altas montañas.

Un enfoque mundial continuo se vuelve complejo realmente rápido, por lo que tiene sentido planificarlo bien: ¿qué información necesita el cliente? ¿Qué información tienen que compartir los servidores? El jugador interactuará principalmente solo con los objetos (incluidos monstruos y NPC) en la misma región. Puede hacer trampa colocando objetos fuera del rango de clic desde el borde de la zona. Esto significa que el cliente está principalmente interesado en la información de solo lectura para las zonas vecinas. Para estos casos, los servidores de zona no tienen que coordinar nada excepto la verificación de permiso de que el jugador está lo suficientemente cerca como para conectarse a una zona vecina.

Esto deja solo un número muy pequeño de casos difíciles en los que los objetos o acciones tienen que cruzar un borde del servidor. Lo cual es bueno porque esos casos como flechas y hechizos son críticos para el rendimiento. Puede ser una buena idea dividir el combate en atacar y defender. Entonces el servidor de un lanzador de hechizos definirá los parámetros de ataque, incluida la posición del lanzador. El servidor del defensor recibirá el mensaje sobre el ataque y calculará el impacto. El servidor del atacante no necesita saber sobre el impacto; el cliente lo aprenderá usando su conexión de solo lectura.

Dependiendo de cuán complejo sea su modelo de reproductor, puede tomar un par de segundos transferirlo a otro servidor (Second Life tiene un gran problema con esto). El problema se puede mitigar preparando la transferencia por adelantado cuando el jugador se acerca a un borde virtual. De modo que la mayoría de los datos del reproductor ya están almacenados en caché en el servidor de destino cuando ocurre la transferencia real.

Resumen

Divida el problema definiendo diferentes servicios que se pueden dividir en servidores con pocas dependencias. Como siguiente paso, mire cómo hacer el equilibrio de carga dentro de los servicios críticos. Delegue el trabajo de equilibrio al cliente indicándole que se conecte directamente a los servidores relevantes (obviamente, los servidores deben verificar los permisos). Manténgalo lo más simple posible, documente bien las responsabilidades de los diversos servicios y servidores, brinde la opción de habilitar la salida de depuración.

PD: algunas de estas técnicas se pueden utilizar para mejorar la fiabilidad. Y debe tener eso en cuenta porque usar muchos servidores implica un riesgo mucho mayor de que las cosas se rompan; no solo en el software sino también a nivel de hardware.

Hendrik Brummermann
fuente
Pero realmente, ¿cómo haces esta comunicación entre procesos? ¿Qué tipo de IPC se debe utilizar?
majidarif
10

En general, el mundo está dividido en varias regiones más pequeñas. Cada una de estas regiones suele ser un proceso de servidor independiente (servidores mundiales de WoW o nodos Sol de Eve) y puede ejecutarse en cualquiera de varias máquinas. En algunos juegos hay puertas explícitas entre mapas (Eve, STO, Guild Wars) mientras que otros intentan enmascarar esto más (WAR, Free Realms). Aquellos que optan por el enfoque más uniforme generalmente detectarán cuando se esté acercando al límite entre dos servidores y los dos procesos negocien una transferencia. El mejor lugar para buscar probablemente una descripción de esto es en cómo las torres de telefonía móvil hacen traspasos de teléfonos móviles. Si la carga de un solo mapa (Jita, Ironforge, Earth Space Dock) es realmente grande, a veces puedes descargar funciones individuales a otros servidores (AI, ciertas partes de la gestión del jugador), pero esto debe incorporarse desde el principio o requeriría una modificación seria. Casi siempre es más rentable comprar un mejor hardware para dedicar a esos pocos mapas.

coderanger
fuente
9

Creo que es un requisito común de los MMO que el procesamiento para un solo fragmento o reino se pueda realizar en varios servidores para facilitar la carga. Tengo curiosidad por saber cómo se puede hacer esto mientras se mantiene un mundo consistente y unificado donde todos los jugadores y todos los NPC pueden interactuar.

Probablemente no sea tan común como piensas; al menos, no si está pensando que un mundo sin interrupciones es administrado por varios servidores simultáneamente.

Sin contar fragmentos totalmente separados, hay 2 direcciones en las que puedes dividir un juego en línea, que podrían considerarse "horizontales" y "verticales":

  • Divide el juego en muchas áreas geográficas separadas. Toda la funcionalidad para cualquier área geográfica determinada es manejada por un servidor y no existe una interacción real entre ellos. (Tenga en cuenta que no necesariamente hay solo 1 zona por servidor: un servidor puede manejar varias zonas simultáneamente, y las zonas tal vez se puedan transferir entre servidores para manejar la carga cambiante).
  • Divide el juego en varios tipos de servicio, por ejemplo. inicio de sesión / autorización, reglas de juego y física, chat + subastas, persistencia, etc. Cada uno de estos servicios puede ser manejado por un servidor diferente. La respuesta de nhnb ha enumerado otros servicios potenciales en los que un desarrollador puede dividir su juego.

Obviamente, estos enfoques son ortogonales y puede combinar los dos. De hecho, es casi obligatorio tener un servidor de base de datos separado, muy común para impulsar el inicio de sesión / autenticación en una máquina separada del juego, y cada vez más común para cultivar el chat y otras comunicaciones no críticas, sin importar cómo sea su mundo de juego está dividido

Pero en general, cuando hay particiones geográficas, la mayoría de los juegos evitan permitirte interactuar a través de esos límites, porque es difícil hacerlo bien. En cambio, recurren a otras formas de hacer que parezca que todavía estás en el mismo fragmento y en el mismo servidor, cuando en realidad no lo estás. p.ej. - pantallas de carga u otras animaciones que cubren un cambio de servidor al hacer la transición entre zonas, o de un continente a otro. - instancias separadas de mazmorras o bandas que están aisladas de todos los demás. Estos son como un fragmento dentro de un fragmento y pueden ejecutarse fácilmente en un servidor separado, lo que ayuda al equilibrio de carga.

No puedo hablar con autoridad sobre WoW, pero supongo que están haciendo casi todo lo anterior: instancias, áreas geográficas separadas que no pueden interactuar unidas por portales de algún tipo, servidores de fondo y de autenticación separados. He oído que los reinos de WoW tienen algo entre 1000 y 10000 jugadores en línea en un reino dado a la vez, lo cual es fácilmente manejable con los esquemas anteriores.

Pero, supongamos que tiene un mundo masivo único y que necesita permitir a los jugadores un servidor para interactuar con jugadores en un servidor adyacente. En teoría, esto es fácil de hacer: primero, los servidores deben cooperar para compartir detalles de los objetos a lo largo de los bordes (por lo que un objeto en un servidor puede tener una representación proxy en otro), y luego simplemente cambiar toda su lógica para pasar mensajes, con los mensajes que se enrutan de un proxy a la fuente autorizada cuando sea necesario. Los mensajes se pueden pasar entre servidores o dentro de un servidor de manera bastante transparente, por lo que un enfoque se adapta a todos los sistemas.

El problema aquí es que la lógica previamente simple puede volverse muy compleja cuando se traduce a mensajes, por ejemplo. un intercambio de 2 jugadores que puede ocurrir de forma segura y atómica cuando ambos jugadores están en un servidor se convierte en un proceso más largo cuando los mensajes tienen que enviarse de un lado a otro, volver a verificar en cada envío y deben establecerse salvaguardas para garantizar que un jugador no pueda explotar el otro cambiando el comercio mientras viaja un mensaje. Ni siquiera puede suponer que el otro jugador seguirá existiendo cuando llegue el mensaje (ya que podrían morir, cerrar sesión, etc.), por lo que el código se vuelve muy complejo. Y esto se aplicará a casi cualquier sistema en el que 2 o más entidades puedan interactuar o cooperar: comercio, combate, agrupación, subastas, botín compartido, entrenamiento, etc.

Estos problemas no son insuperables, pero para la mayoría de los juegos son demasiado difíciles de intentar cuando puedes compartir la carga por otros medios y mantener toda la lógica del juego en un servidor. Así que casi todos los juegos actuales siguen ese camino.

Kylotan
fuente
3

Hay muchos métodos para equilibrar la carga de un servidor MMO, ya que hay una amplia gama de datos para procesar. Prefiero el método del árbol bin del proceso.

Un servidor global pasa las conexiones de usuario a un contenedor de proceso que puede manejar varios usuarios a la vez. los contenedores de proceso realizan todo el procesamiento complejo y solo responden al servidor global con datos que son relevantes a nivel mundial, como el chat global y el posicionamiento. Este método se equilibra mucho mejor que los servidores de la región, ya que las regiones pueden variar mucho en población, mientras que el procesamiento general del usuario varía lo suficiente como para que se equilibre naturalmente en su mayor parte.

Simplemente realice un equilibrio de carga básico a través del servidor global, de modo que cuando un bin de proceso alcance un cierto uso de memoria / CPU, inicie un nuevo servidor de bin de proceso.

Stephen Belanger
fuente
¿Cómo se comparten los datos compartidos entre las bandejas de proceso, por ejemplo, una pelea entre dos usuarios en diferentes bandejas de proceso? ¿Cómo se asegura el orden de los eventos? Para que un jugador muerto ya no pueda hacer ningún ataque, incluso si el contenedor que lo mata es más lento que el que realiza el ataque. ¿Existe el riesgo de que los gastos generales de envío lleguen a un nivel alto en el servidor global? El modelo de proxy para las conexiones de usuario puede entrar en los límites del sistema operativo en la pila de red.
Hendrik Brummermann
Este modelo funciona bastante bien en sistemas de información donde la mayoría de las transacciones están aisladas. Quiero decir que generalmente no funcionan con los mismos datos, y en los raros casos se usa el bloqueo o la reversión. Pero en los juegos donde las peleas incluyen múltiples jugadores y / o criaturas, y el impacto de los ataques está influenciado por los atributos del atacante y el defensor, este enfoque puede ser difícil.
Hendrik Brummermann
Puede seguir el camino fácil y considerar que las interacciones multiusuario son relevantes a nivel mundial, o puede crear un método simple para que los contenedores de procesos se conozcan y se comuniquen entre sí. Cada bin de proceso debería ser capaz de manejar a unos diez mil usuarios a la vez, por lo que la comunicación de estado entre usuarios no debería ser un gran problema. El método de región es un poco más fácil, pero no tan equilibrado, y puede bloquearse fácilmente si demasiados usuarios ingresan a la misma región. En un MMORPG con una gran base de usuarios, equilibrar la carga de manera uniforme es muy importante.
Stephen Belanger
Me encantaría saber "un método simple" para 2 contenedores de proceso para poder negociar un sistema como el combate. El problema no son las comunicaciones de bajo nivel, sino que los algoritmos de juego típicos se vuelven muy complicados con los participantes distribuidos.
Kylotan
En mi implementación, mi servidor global mantiene una lista de todos los clientes conectados y realiza un seguimiento de a qué bin de proceso están conectados. Si un bin de proceso necesita acceder a otro usuario, primero verifica su propia lista de usuarios. Si eso falla, verifica la lista global e identifica a qué bin de proceso se conecta el otro usuario. Los contenedores de proceso se conectan directamente para compartir los estados de los usuarios mientras realiza el procesamiento unificado.
Stephen Belanger