Cómo Balancear la Carga de Servidores MU Online
Aprende a balancear la carga entre múltiples procesos GameServer en MU Online para mantener alta disponibilidad y latencia baja con muchos jugadores.
Cómo Funciona el Balanceo de Carga en MU Online
Antes de realizar cualquier cambio en la configuración, es fundamental entender de qué manera los distintos componentes del servidor interactúan entre sí para distribuir la carga de jugadores. El ecosistema de un servidor MU Online privado está formado por varios procesos que cooperan: ConnectServer, JoinServer, uno o más procesos GameServer, DataServer y servicios auxiliares como EventServer y CastleServer.
El flujo de una conexión nueva funciona de la siguiente manera. Cuando un cliente abre el juego, establece contacto con el ConnectServer, que le entrega la lista de canales disponibles. Al seleccionar un canal, el cliente consulta al JoinServer, que decide hacia qué GameServer redirigirlo basándose en la ocupación actual de cada instancia. El JoinServer conoce en todo momento la cantidad de jugadores conectados a cada proceso gracias a los mensajes de estado que los GameServers le envían periódicamente.
Esta arquitectura significa que el balanceo de carga en MU Online no requiere software externo como HAProxy o Nginx para la distribución de jugadores: el propio JoinServer es el balanceador nativo. Sin embargo, sí es posible complementarlo con técnicas adicionales a nivel de sistema operativo o red para mejorar la disponibilidad y la tolerancia a fallos.
Preparar el Entorno para Múltiples GameServers
El primer paso es asegurarse de que la instalación base funciona correctamente con un solo GameServer antes de agregar instancias adicionales. Una configuración inestable con un proceso difícilmente mejorará al multiplicarlo.
Revisa los archivos de configuración clave y planifica la asignación de puertos e IDs antes de duplicar cualquier proceso:
Componente → Puerto predeterminado → ID configurable
ConnectServer → 44405 → (único, no aplica ID)
JoinServer → 55557 → (único, no aplica ID)
GameServer 1 → 55901 (clientes) → ServerCode = 0
→ 55980 (JoinServer)
GameServer 2 → 55902 (clientes) → ServerCode = 1
→ 55981 (JoinServer)
GameServer 3 → 55903 (clientes) → ServerCode = 2
→ 55982 (JoinServer)
DataServer → 55980 (interno) → (único, no aplica ID)
Cada GameServer necesita su propio directorio con una copia completa de sus archivos de configuración. La práctica recomendada es crear una estructura como:
C:\MuServer\
GameServer1\ → ServerCode 0, puerto 55901
GameServer2\ → ServerCode 1, puerto 55902
GameServer3\ → ServerCode 2, puerto 55903
JoinServer\
ConnectServer\
DataServer\
> [!CONSEJO] > Nombra las carpetas con el número de instancia desde el principio. Renombrar directorios después de configurar los archivos .ini genera confusión y puede provocar errores difíciles de rastrear. Establece la convención desde el primer momento.
Configurar el JoinServer para Balancear Múltiples Instancias
El JoinServer reconoce a los GameServers a través de su archivo de configuración principal, habitualmente llamado JoinServer.ini o ServerInfo.ini según la versión del emulador. Debes registrar cada instancia adicional en la sección correspondiente.
Un bloque de configuración típico para tres GameServers luce así:
[ServerList]
ServerCount = 3
[Server0]
ServerCode = 0
ServerName = Loto
MaxUsers = 800
IP = 127.0.0.1
Port = 55980
[Server1]
ServerCode = 1
ServerName = Vid
MaxUsers = 800
IP = 127.0.0.1
Port = 55981
[Server2]
ServerCode = 2
ServerName = Bali
MaxUsers = 800
IP = 127.0.0.1
Port = 55982
El campo MaxUsers es especialmente importante para el balanceo: el JoinServer usará este valor como referencia para calcular el porcentaje de ocupación de cada instancia. Si un GameServer alcanza su MaxUsers, el JoinServer dejará de redirigir jugadores nuevos hacia él hasta que alguno se desconecte.
El campo IP debe ser 127.0.0.1 cuando todos los procesos corren en la misma máquina física. Si un GameServer corre en un host remoto dentro de la misma red local, usa su IP privada. Si se encuentra en un servidor completamente separado accesible solo por IP pública, usa esa IP pública, y asegúrate de que los puertos internos estén abiertos y correctamente reenviados en el firewall.
Configurar Cada Instancia de GameServer
Dentro del directorio de cada GameServer, edita su archivo principal de configuración (usualmente GameServer.ini o similar) y ajusta al menos los siguientes valores para que sean únicos por instancia:
[GameServer]
ServerCode = 1 → ID numérico único, debe coincidir con JoinServer
ServerName = Vid → Nombre que verán los jugadores en la lista
GameServerPort = 55902 → Puerto de escucha para clientes
JoinServerPort = 55981 → Puerto para comunicarse con JoinServer
JoinServerIP = 127.0.0.1
MaxUsers = 800
El error más frecuente es copiar el directorio de GameServer1 para crear GameServer2 y olvidar cambiar el ServerCode y los puertos. Dos procesos con el mismo ServerCode provocan conflictos en el JoinServer y comportamientos impredecibles: jugadores que no pueden iniciar sesión, personajes que aparecen duplicados en distintos canales o datos que no se guardan correctamente.
> [!ATENCION] > Nunca arranques dos instancias de GameServer con el mismo ServerCode al mismo tiempo. Si el JoinServer detecta dos registros con el mismo código, el comportamiento depende de la implementación del emulador: algunas versiones simplemente rechazan la segunda conexión, pero otras la aceptan y corrompen el registro de jugadores activos, lo que puede causar pérdida de datos de personajes.
Distribuir Mapas Entre Instancias
Una estrategia avanzada de balanceo consiste en asignar mapas específicos a instancias específicas de GameServer. Esto es especialmente útil cuando ciertos mapas concentran tráfico de forma desproporcionada, como Lorencia (mapa 0) en servidores con muchos jugadores nuevos, o mapas de evento masivo como Blood Castle y Chaos Castle.
La asignación de mapas se controla en el archivo de configuración de mapas del GameServer, habitualmente MapServerInfo.ini o dentro de la sección [Maps] del archivo principal:
; GameServer1 — mapas de bajo nivel y ciudad principal
[Maps]
Map0 = 1 → Lorencia
Map1 = 1 → Noria
Map2 = 1 → Devias
Map7 = 1 → Atlans
Map33 = 0 → Kalima (desactivado en esta instancia)
; GameServer2 — mapas de nivel medio y alto
[Maps]
Map0 = 0 → Lorencia (desactivado aquí)
Map4 = 1 → Lost Tower
Map10 = 1 → Icarus
Map33 = 1 → Kalima
Con esta distribución, un jugador que intenta entrar a Lorencia siempre será dirigido al GameServer1, mientras que los jugadores de Icarus estarán en el GameServer2. El ConnectServer y el JoinServer deben conocer esta asignación para redirigir correctamente. Consulta la documentación de tu emulador específico para la sintaxis exacta de la sección de mapas, ya que varía entre versiones de Season.
Monitorear y Ajustar el Balanceo en Producción
Una vez que los procesos están corriendo, el monitoreo continuo es la única forma de saber si el balanceo está funcionando como se espera. Revisa los siguientes indicadores de forma regular:
Logs del JoinServer: busca líneas que indiquen la distribución de jugadores por instancia. Un balanceo sano mostrará contadores similares en todos los GameServers durante las horas pico. Si uno de ellos siempre tiene el doble de jugadores que los demás, revisa si su MaxUsers es el correcto o si el ConnectServer está priorizando ese canal por algún motivo de configuración.
Uso de CPU por proceso: en el Administrador de tareas de Windows, cada GameServer aparece como un proceso separado. Durante las horas pico, ningún proceso debería superar el 80-85 % de uso de CPU de forma sostenida. Si uno de ellos alcanza ese límite mientras los demás tienen CPU disponible, el balanceo no está distribuyendo la carga equitativamente.
Latencia reportada por los jugadores: pide a jugadores de distintos canales que reporten su ping al servidor. Si un canal específico tiene latencia consistentemente más alta que los demás, ese GameServer puede estar sobrecargado o tener un problema de red.
> [!CONSEJO] > Crea un script de monitoreo simple que lea los logs del JoinServer cada 5 minutos y escriba en un archivo de texto el conteo de jugadores por instancia con marca de tiempo. Revisar ese archivo al final del día te dará una imagen clara de los picos de tráfico y de cómo se está distribuyendo la carga a lo largo del tiempo, sin necesidad de herramientas externas.
Ajustar el valor de MaxUsers en el JoinServer es la palanca principal para modificar el comportamiento del balanceo sin reiniciar procesos. Si bajas el MaxUsers de una instancia, el JoinServer empezará a redirigir más jugadores nuevos a las demás instancias aunque la primera aún tenga capacidad real disponible. Esto es útil cuando quieres vaciar gradualmente un GameServer para realizar mantenimiento sin desconectar a los jugadores presentes.
Perguntas frequentes
¿Qué componente es responsable de distribuir jugadores entre los GameServers?
El JoinServer es el componente central del balanceo de carga nativo de MU Online. Mantiene un registro en tiempo real de cuántos jugadores están conectados a cada instancia de GameServer y, cuando un cliente nuevo solicita ingresar, redirige la conexión al GameServer con menor ocupación. El ConnectServer actúa como punto de entrada inicial y delega al JoinServer la decisión de hacia qué canal enviar cada jugador.
¿Puedo correr varios GameServers en la misma máquina física?
Sí, siempre que la máquina tenga suficiente CPU y RAM disponibles. Cada instancia de GameServer es un proceso independiente que consume entre 300 MB y 600 MB de RAM según la cantidad de mapas cargados. Para dos instancias activas en un servidor de producción, se recomienda un mínimo de 8 GB de RAM y un procesador con 4 núcleos físicos. Asigna un puerto de escucha único a cada proceso para evitar conflictos.
¿Cómo sé si el balanceo está funcionando correctamente?
La forma más directa es observar los logs del JoinServer (normalmente en la carpeta logs/ de su directorio de instalación). Cada vez que un jugador inicia sesión, el JoinServer registra el servidor de destino elegido y los contadores actuales. Si siempre redirige al mismo GameServer ignorando los demás, revisa que todos los procesos estén registrados en ServerList.dat y que sus estados aparezcan como activos en los logs de ConnectServer.
¿El balanceo de carga afecta el rendimiento de la base de datos SQL?
El balanceo distribuye la carga de red y CPU entre los procesos GameServer, pero todos siguen compartiendo el mismo DataServer y, por extensión, el mismo SQL Server. Si la base de datos se convierte en el cuello de botella, el balanceo de carga no lo resolverá. En ese caso, debes optimizar las consultas SQL, agregar índices a las tablas más consultadas (Character, AccountCharacter, Warehouse) y considerar separar el DataServer en una máquina dedicada con discos de alta velocidad.