Cómo configurar subservidores (channels) en MU Online
Aprende a dividir tu servidor de MU Online en múltiples channels (subservidores) que comparten la misma base de datos, distribuyendo la carga de jugadores entre instancias y sabiendo el momento justo de dividir.
A medida que un servidor de MU Online crece, llega el momento en que un único GameServer ya no da abasto con el volumen de jugadores simultáneos: empiezan a aparecer lag en áreas llenas, retraso en eventos y picos de CPU que degradan la experiencia de todos al mismo tiempo. La respuesta clásica para
A medida que un servidor de MU Online crece, llega el momento en que un único GameServer ya no da abasto con el volumen de jugadores simultáneos: empiezan a aparecer lag en áreas llenas, retraso en eventos y picos de CPU que degradan la experiencia de todos al mismo tiempo. La respuesta clásica para esto es dividir el servidor en subservidores, también llamados channels — múltiples instancias de GameServer que comparten la misma base de datos y los mismos personajes, pero distribuyen a los jugadores en procesos separados. El jugador sigue siendo el mismo en cualquier channel; solo elige, en la pantalla de selección, a qué instancia quiere entrar. Este modelo aumenta la capacidad total, reduce la concentración en una única instancia y además permite un mantenimiento más granular. Este tutorial cubre la arquitectura multi-channel, la configuración de puertos, la ServerList del ConnectServer, estrategias de balanceo de jugadores y —lo más importante— el momento justo de dividir, para que no agregues complejidad antes de tiempo.
Qué son los channels (subservidores)
Un channel es una instancia de GameServer que forma parte del mismo servidor lógico. Todos los channels de un servidor:
- Comparten la misma base de datos — cuentas, personajes, ítems, guild, ranking son únicos.
- Aparecen en la misma pantalla de selección (Channel 1, Channel 2...), servidos por el mismo ConnectServer.
- Tienen el mismo contenido — mapas, drops, rates suelen ser idénticos (aunque es posible diferenciar rates por channel, ese no es el uso más común).
La diferencia esencial respecto a correr dos servidores separados es la base de datos compartida. Con channels, el personaje "Guerrero01" existe una sola vez y puede entrar por cualquier channel. Esto es fundamental: los channels sirven para escalar capacidad, no para crear mundos diferentes.
Arquitectura multi-channel
El diseño típico con base única y varios GameServers:
BASE SQL (única)
│
┌──────────┼──────────┐
│ │ │
DataServer DataServer DataServer
│ │ │
JoinServer JoinServer JoinServer
│ │ │
GameServer GameServer GameServer
Channel 1 Channel 2 Channel 3
(porta 55901)(porta 55902)(porta 55903)
│ │ │
└──────────┼──────────┘
│
ConnectServer
(porta 44405)
│
JUGADOR
(ve la lista de channels)
Cada channel es una pila completa (DataServer + JoinServer + GameServer) apuntando a la misma base. El ConnectServer centraliza las conexiones y muestra los channels disponibles.
Requisitos previos
- Un servidor de MU Online ya funcional con un único channel estable. Si aún estás armando el servidor base, mira la guía de cómo crear un servidor de MU Online.
- Máquina (VPS/dedicado) con holgura de recursos: cada channel adicional consume CPU y RAM.
- SQL Server con la base única (estándar MuOnline) y DSN ODBC 32-bit configurada.
- Acceso administrativo para abrir puertos en el firewall.
- Editor de texto que preserve la codificación (Notepad++/VS Code), pues
ServerList.txty.inison sensibles. - Entendimiento claro de que todos los channels usan la misma base: jamás apuntes un channel a otra base por error.
- Backup completo antes de cualquier cambio.
> No confundas los channels con servidores independientes. Si apuntas cada channel a una base diferente, dejas de tener channels y pasas a tener dos servidores desconectados. La base compartida es lo que define el modelo.
Paso 1 — Estructura de carpetas por channel
Cada channel necesita su propia carpeta y sus propios archivos de configuración:
MuServer/
├── Channel1/
│ ├── DataServer/
│ ├── JoinServer/
│ └── GameServer/
├── Channel2/
│ ├── DataServer/
│ ├── JoinServer/
│ └── GameServer/
└── ConnectServer/
├── ConnectServer.exe
└── ServerList.txt
El ConnectServer es único y sirve a todos los channels: no se duplica.
Paso 2 — Puertos por channel
Como todos los channels viven en la misma máquina, cada proceso de red necesita un puerto único. Solo la base es compartida. Un esquema de ejemplo (las claves y puertos varían según el emulador):
| Proceso | Channel 1 | Channel 2 | Channel 3 | ¿Expuesto? |
|---|---|---|---|---|
| GameServer | 55901 | 55902 | 55903 | Sí |
| DataServer | 55557 | 55567 | 55577 | No |
| JoinServer | 55555 | 55565 | 55575 | No |
| ServerCode | 0 | 1 | 2 | — |
| ConnectServer | 44405 (compartido) | Sí |
El ServerCode (también llamado código de servidor) debe ser único por channel y coincidir con lo que esté en la ServerList.
Paso 3 — Configurar los GameServers
Cada channel recibe un GameServer.ini con su ServerCode y sus puertos, pero con la misma DSN:
; Channel1/GameServer/GameServer.ini
[General]
ServerCode=0
ServerName=Channel 1
[Network]
GameServerPort=55901
[JoinServer]
JoinServerIP=127.0.0.1
JoinServerPort=55555
[Database]
DSN=MuOnline ; misma base en TODOS los channels
; Channel2/GameServer/GameServer.ini
[General]
ServerCode=1
ServerName=Channel 2
[Network]
GameServerPort=55902 ; puerto diferente
[JoinServer]
JoinServerIP=127.0.0.1
JoinServerPort=55565 ; puerto diferente
[Database]
DSN=MuOnline ; MISMA base
Haz lo mismo para los DataServer.ini y JoinServer.ini de cada channel, siempre con puertos distintos y la misma DSN.
Paso 4 — Configurar la ServerList del ConnectServer
El ConnectServer lee la lista de channels y la presenta al cliente. El formato clásico del ServerList.txt (varía según el emulador; algunas distros usan Setting.xml):
; ServerList.txt
; Formato: Index IP Port Nombre MaxUsers Fill
; Fill = indicador visual de ocupación (0=vacío ... 30=lleno)
0 TU_IP 55901 "Channel 1" 1000 0
1 TU_IP 55902 "Channel 2" 1000 0
2 TU_IP 55903 "Channel 3" 1000 0
Versión en XML, común en distribuciones más recientes:
<?xml version="1.0" encoding="utf-8"?>
<ServerList>
<Server>
<ServerCode>0</ServerCode>
<ServerName>Channel 1</ServerName>
<IP>TU_IP</IP>
<Port>55901</Port>
<MaxUsers>1000</MaxUsers>
<Visible>1</Visible>
</Server>
<Server>
<ServerCode>1</ServerCode>
<ServerName>Channel 2</ServerName>
<IP>TU_IP</IP>
<Port>55902</Port>
<MaxUsers>1000</MaxUsers>
<Visible>1</Visible>
</Server>
</ServerList>
El ServerCode de cada entrada debe coincidir con el ServerCode del GameServer.ini correspondiente, o el jugador es enviado al channel equivocado.
Paso 5 — Firewall
Abre solo el ConnectServer y los GameServers; mantén DataServer y JoinServer internos:
netsh advfirewall firewall add rule name="MU Connect" dir=in action=allow protocol=TCP localport=44405
netsh advfirewall firewall add rule name="MU Ch1" dir=in action=allow protocol=TCP localport=55901
netsh advfirewall firewall add rule name="MU Ch2" dir=in action=allow protocol=TCP localport=55902
# DataServer/JoinServer (55557,55555,55567,55565): NO exponer a internet
Paso 6 — Orden de inicio
Levanta los procesos de cada channel en el orden canónico y deja el ConnectServer para el final:
@echo off
start "" "MuServer\Channel1\DataServer\DataServer.exe"
timeout /t 3
start "" "MuServer\Channel1\JoinServer\JoinServer.exe"
timeout /t 3
start "" "MuServer\Channel1\GameServer\GameServer.exe"
timeout /t 5
start "" "MuServer\Channel2\DataServer\DataServer.exe"
timeout /t 3
start "" "MuServer\Channel2\JoinServer\JoinServer.exe"
timeout /t 3
start "" "MuServer\Channel2\GameServer\GameServer.exe"
timeout /t 5
start "" "MuServer\ConnectServer\ConnectServer.exe"
echo Todos los channels en linea.
Balanceo de jugadores
Distribuir a los jugadores de forma equilibrada entre los channels es lo que garantiza el beneficio de rendimiento. Estrategias comunes:
- Indicador de ocupación (Fill/CurrentUsers): haz que el ConnectServer refleje la ocupación real. Así los propios jugadores tienden a elegir el channel menos lleno.
- Ordenar la lista por el menos ocupado: algunas distros permiten que el channel con menos gente aparezca primero.
- MaxUsers por channel: define un tope por channel para que, al llenarse, deje de aceptar conexiones y empuje a los nuevos jugadores a otro.
- Monitoreo activo: sigue la distribución por la base de datos.
-- Online por channel (si el GameServer registra la sesión con ServerCode)
SELECT ServerCode, COUNT(*) AS Online
FROM GameServerSessions -- el nombre de la tabla varía por distribución
WHERE IsOnline = 1
GROUP BY ServerCode
ORDER BY Online DESC;
-- Total general online
SELECT COUNT(*) AS TotalOnline
FROM Character
WHERE ConnectStat = 1;
Recuerda que, al compartir la base, los ítems en NPCs personales, guild, ranking y comercio quedan consistentes entre los channels: el jugador cambia de channel sin perder nada.
Cuándo dividir en channels (y cuándo no)
Divide cuando: tu único channel se acerca al límite práctico de jugadores simultáneos del emulador; observas lag y CPU alta concentrados en horarios pico; o áreas específicas (ciudades, spots de eventos) quedan intransitables de tan llenas. No dividas demasiado pronto: un servidor recién lanzado, con pocas decenas de online, solo gana complejidad de mantenimiento sin beneficio real con múltiples channels. Como regla práctica, mantén un único channel mientras esté cómodo y agrega el segundo cuando la ocupación pico supere de forma consistente cerca del 70% de la capacidad estable del primero.
Errores comunes y soluciones
| Síntoma | Causa probable | Solución |
|---|---|---|
| El jugador entra al channel equivocado | El ServerCode de la ServerList no coincide con el del GameServer | Alinea los ServerCodes entre la ServerList y cada GameServer.ini |
| El channel no aparece en la selección | Entrada ausente o Visible=0 en la ServerList | Agrega/activa la entrada y reinicia el ConnectServer |
| El personaje "desaparece" al cambiar de channel | Channels apuntando a bases diferentes | Apunta todos a la MISMA DSN/base |
| El segundo GameServer no levanta | Puerto duplicado con el primer channel | Ajusta los puertos del Channel 2 (Game/Data/Join) |
| Un channel siempre lleno, otro vacío | Sin indicador de ocupación/ordenación | Activa Fill/CurrentUsers y ordena por el menos lleno |
| El lag continúa tras dividir | Cuello de botella en la base, no en el GameServer | Optimiza índices/consultas; verifica el disco (SSD) |
Lista de verificación de lanzamiento
- Backup completo del servidor y de la base realizado
- Necesidad de channels confirmada por datos de ocupación/CPU
- Carpeta separada para cada channel
- Puertos únicos por proceso en cada channel (Game/Data/Join)
- ServerCode único por channel
- Todos los channels apuntando a la MISMA DSN/base
- ServerList (o Setting.xml) con una entrada por channel y ServerCodes coincidiendo
- Firewall abriendo solo ConnectServer y GameServers
- DataServer/JoinServer cerrados a internet
- Indicador de ocupación/MaxUsers configurado para el balanceo
.batde inicio en el orden correcto- Prueba: el cliente ve todos los channels en la selección
- Prueba: entrar en cada channel y confirmar el mismo personaje
- Prueba: cambiar de channel sin perder ítems/guild/ranking
- Monitoreo de online por channel funcionando
Con los channels bien configurados —puertos únicos, ServerCodes alineados y base única compartida— tu servidor de MU Online escala para muchos más jugadores simultáneos sin sacrificar la estabilidad. Adopta la división guiado por datos de ocupación, valida el cambio de channel con pruebas reales de personaje, y mantén el balanceo siempre bajo control para que la capacidad extra se traduzca en una jugabilidad fluida para todos.
Preguntas frecuentes
¿Cuál es la diferencia entre channels y servidores independientes?
Los channels (subservidores) comparten la MISMA base de datos y los MISMOS personajes: el jugador es el mismo en cualquier channel, solo distribuido en instancias diferentes para aliviar la carga. Los servidores independientes tienen bases, cuentas y personajes separados. El channel es sobre capacidad; el servidor separado es sobre proyectos distintos.
¿Cuántos channels debo crear?
Empieza con el mínimo necesario. Un único GameServer suele aguantar de algunos cientos a más de mil jugadores según el emulador y el hardware. Solo agrega un segundo channel cuando el primero se acerque al límite práctico de players simultáneos o de CPU.
¿Los channels necesitan puertos diferentes?
Sí. Cada GameServer/channel en la misma máquina necesita un puerto único (ej.: 55901, 55902, 55903). El DataServer y el JoinServer de cada channel también necesitan puertos propios. Solo la base de datos es compartida.
¿Cómo elige el jugador el channel?
Por el ConnectServer. Lee la ServerList y presenta al cliente la lista de channels disponibles (Channel 1, Channel 2...), muchas veces con un indicador de ocupación. El jugador elige y es redirigido al GameServer de ese channel.
¿Puedo tener channels en máquinas diferentes?
Sí. En servidores grandes, cada channel puede correr en una VPS distinta, todos apuntando a la misma base central. La ServerList del ConnectServer usa las IPs reales de cada máquina. Esto exige baja latencia entre los servidores y la base.