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.
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.
fuente
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":
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.
fuente
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.
fuente