El mayor portal de MU Online de Brasil — desde 2003
Tutorial Avanzado Servidor

Cómo automatizar pruebas de carga en el GameServer de tu servidor de MU Online

Arma un pipeline de pruebas de carga que simula cientos de conexiones simultáneas en el ConnectServer y GameServer de tu servidor de MU Online, midiendo latencia, uso de CPU/memoria y el límite real antes del lanzamiento.

RO Rodrigo · Actualizado el 28 sep 2017 · ⏱ 17 min de lectura
Respuesta rápida

Lanzar un servidor de MU Online sin saber cuántos jugadores simultáneos soporta realmente es una apuesta a ciegas: el primer día de difusión, cuando más gente intenta entrar al mismo tiempo, es justamente el peor momento para descubrir que el ConnectServer se traba en 200 conexiones o que la base de

Lanzar un servidor de MU Online sin saber cuántos jugadores simultáneos soporta realmente es una apuesta a ciegas: el primer día de difusión, cuando más gente intenta entrar al mismo tiempo, es justamente el peor momento para descubrir que el ConnectServer se traba en 200 conexiones o que la base de datos satura el pool antes de lo esperado. Este tutorial muestra cómo armar un pipeline de prueba de carga automatizado, simulando conexiones y acciones simultáneas en el ConnectServer y GameServer, midiendo los indicadores correctos e identificando el límite real de tu entorno antes de que los jugadores lo hagan por vos.

Por qué probar la carga antes del lanzamiento

Una difusión exitosa (grupos, YouTube, Discords aliados) suele generar un pico de accesos concentrado en las primeras horas después del lanzamiento — muy por encima del promedio que el servidor va a sostener después. Si el entorno se rompe en ese pico, la primera impresión de los jugadores es pésima y buena parte no vuelve a intentar. Probar la carga con anticipación permite corregir cuellos de botella (configuración de base de datos, hardware subdimensionado, límite de conexiones del SO) mientras todavía no hay jugadores reales en riesgo.

Diferenciando los tipos de prueba

No toda prueba de carga necesita simular el juego entero. Dividir por capa facilita aislar dónde está el cuello de botella:

Tipo de pruebaQué simulaHerramienta típica
Prueba de conexión (login)Cientos de handshakes simultáneos en el ConnectServerScript propio (Python/C#) emulando el protocolo
Prueba de autenticaciónLogin + selección de personaje en el GameServerScript con el protocolo de login del emulador
Prueba de gameplayMovimiento, ataque, cambio de mapa, uso de NPCBots que juegan de verdad (más costoso)
Prueba de base de datosConcurrencia de lectura/escritura en MEMB_INFO, Charactersysbench o script SQL directo
Prueba de red/infraAncho de banda, latencia, paquetes perdidosiperf3, monitoreo de interfaz

Preparando el entorno de staging

Nunca corras la prueba de carga contra la base de datos/servidor de producción — el riesgo de corromper datos reales o tumbar el servidor durante la difusión es demasiado alto. Cloná la configuración (mismas versiones de emulador, misma configuración de base de datos, hardware lo más parecido posible) en un entorno aislado, con datos de prueba sintéticos:

CREATE DATABASE mu_staging;
-- Restaurá un dump limpio/sintético, nunca datos reales de jugadores

Simulando conexiones en el ConnectServer

El ConnectServer es el primer cuello de botella en un pico de acceso — resuelve a qué GameServer debe ir el cliente y mantiene una cola de conexiones. Un script simple en Python, usando sockets crudos, puede simular cientos de handshakes:

import socket
import threading
import time

def simular_conexao(host, porta, resultados, i):
    inicio = time.time()
    try:
        s = socket.create_connection((host, porta), timeout=5)
        s.close()
        resultados.append(time.time() - inicio)
    except Exception as e:
        resultados.append(None)

resultados = []
threads = []
for i in range(500):
    t = threading.Thread(target=simular_conexao, args=("staging.miservidor.com", 44405, resultados, i))
    threads.append(t)
    t.start()
    time.sleep(0.01)  # espacia levemente para simular llegada gradual

for t in threads:
    t.join()

sucesso = [r for r in resultados if r is not None]
print(f"Conexiones exitosas: {len(sucesso)}/{len(resultados)}")
print(f"Latencia promedio: {sum(sucesso)/len(sucesso):.3f}s")

Esta prueba básica ya revela si el ConnectServer acepta las conexiones rápidamente o empieza a encolar/rechazar por encima de determinado volumen.

Simulando el flujo de login completo

Para medir el cuello de botella real de autenticación (que involucra la consulta a la base de cuentas), hay que emular el protocolo de paquetes de tu emulador — la estructura varía entre IGCN, MuEMU y X-Team, pero el principio es el mismo: armar el paquete de login binario y leer la respuesta:

import struct

def montar_pacote_login(conta, senha):
    # Estructura simplificada — ajustá a los offsets reales de tu emulador
    corpo = conta.encode('ascii').ljust(10, b'\x00') + senha.encode('ascii').ljust(10, b'\x00')
    tamanho = len(corpo) + 4
    return struct.pack('BBB', 0xC1, tamanho, 0xF1) + corpo

Correr este paquete de forma concurrente contra el GameServer de staging, midiendo el tiempo hasta la respuesta de éxito/falla, muestra la capacidad real de autenticación simultánea — generalmente el cuello de botella aparece primero acá, no en la conexión TCP en sí.

Probando concurrencia en la base de datos

Independientemente de la prueba de red, la base de datos suele ser el límite real de escala. Usá sysbench para simular carga de lectura/escritura equivalente al patrón de acceso del servidor (muchas lecturas de personaje, pocas escrituras de posición cada pocos segundos):

sysbench oltp_read_write \
  --db-driver=mysql --mysql-db=mu_staging \
  --mysql-user=teste --mysql-password=senha \
  --tables=10 --table-size=100000 \
  --threads=200 --time=120 \
  run

Comparé los resultados de latencia (p95, p99) de sysbench con el número de jugadores simultáneos esperado — si el p99 ya se degrada con 200 threads simulados y tu meta es 500 CCU, la base de datos (no el GameServer) es el cuello de botella a resolver primero.

Monitoreando recursos durante la prueba

Mientras la prueba corre, recolectá métricas del sistema en paralelo para correlacionar carga con consumo de recursos:

# En una ventana separada, durante toda la prueba:
top -b -n 100 -d 5 | grep -E "GameServer|ConnectServer|mysqld" >> /tmp/monitor_carga.log
vmstat 5 100 >> /tmp/monitor_carga.log
MétricaHerramientaQué indica
CPU del proceso GameServertop/htopCuello de botella de procesamiento de lógica de juego
Memoria residentetop/psFuga de memoria bajo carga prolongada
Conexiones activas en MySQLSHOW PROCESSLIST;Saturación del pool de conexiones
Latencia de discoiostat -x 5Cuello de botella de I/O en bases grandes
Paquetes perdidos/latencia de rediperf3, ping -fLímite de ancho de banda o configuración de red

Definiendo los escenarios de prueba (rampa gradual)

En vez de disparar todos los "jugadores simulados" de una vez (lo que no refleja el patrón real de llegada), estructurá la prueba en rampa — aumentando la carga gradualmente y observando en qué punto cada métrica empieza a degradarse:

FaseCCU simuladoDuraciónObjetivo
Calentamiento502 minConfirmar la línea base sin carga
Rampa 11505 minMeta mínima de lanzamiento
Rampa 23005 minMeta esperada de pico
Rampa 35005 minEstrés por encima de la meta (margen de seguridad)
Rampa 4700+hasta romperIdentificar el punto de ruptura real

Automatizando la ejecución del pipeline completo

Un script orquestador simple encadena las etapas y guarda los resultados con timestamp, para comparar ejecuciones a lo largo del tiempo (por ejemplo, antes y después de una optimización de configuración):

#!/bin/bash
DATA=$(date +%F_%H%M)
mkdir -p /tests/$DATA

python3 teste_conexao.py > /tests/$DATA/conexao.log &
sysbench oltp_read_write --threads=200 --time=300 run > /tests/$DATA/banco.log &
top -b -d 5 -n 60 > /tests/$DATA/recursos.log &

wait
echo "Prueba de carga $DATA completada. Resultados en /tests/$DATA/"

Interpretando los resultados y actuando sobre ellos

El objetivo final no es solo generar números, es decidir acciones concretas. Un resultado típico de análisis:

  • Si la latencia de login se degrada antes de que la CPU del GameServer sature, el cuello de botella es el pool de conexiones de la base de datos — aumentá max_connections en MySQL/MSSQL y ajustá el pool del emulador.
  • Si la CPU del GameServer satura primero, el hardware está subdimensionado para la meta de CCU — considerá un upgrade de vCPU u optimizar la lógica de eventos que corren en loop.
  • Si la red se degrada con pocos cientos de conexiones, el enlace contratado puede ser insuficiente para el volumen esperado — revisá el plan con el proveedor.

Errores comunes y soluciones

SíntomaCausa probableSolución
La prueba tumba el entorno de staging rápidamenteRampa demasiado agresiva desde el inicioUsá una rampa gradual (50 → 150 → 300 → 500)
Los resultados no son reproduciblesEntorno de staging con hardware distinto al de producciónAlineá las specs de CPU/RAM/disco entre staging y producción
Latencia alta pero CPU/memoria OKCuello de botella de base de datos (pool o índice)Corré sysbench aislado y revisá SHOW PROCESSLIST
El script de simulación se traba con error de socketLímite de conexiones del SO (ulimit) alcanzado en el cliente de la pruebaAumentá ulimit -n en la máquina que genera la carga
La prueba no revela nada útilMétricas de sistema no recolectadas durante la ejecuciónCorré top/vmstat/iostat en paralelo, siempre
Producción se rompe aun después de una prueba "aprobada"La prueba solo cubrió la capa de conexión, no el gameplay realComplementá con una prueba de bots simulando acciones reales

Lista de verificación de prueba de carga

  • Entorno de staging aislado, con specs equivalentes a producción.
  • Script de simulación de conexión en el ConnectServer funcionando.
  • Script de simulación de login/autenticación probado.
  • Prueba de concurrencia de base de datos (sysbench) ejecutada y analizada.
  • Monitoreo de CPU, memoria, conexiones y disco recolectado durante la prueba.
  • Rampa gradual de carga ejecutada hasta identificar el punto de ruptura.
  • Acciones correctivas definidas en base a los cuellos de botella encontrados.
  • Reprueba realizada después de los ajustes para confirmar la mejora.

Con el límite real de tu entorno mapeado antes del lanzamiento, cambiás las sorpresas de producción por decisiones de dimensionamiento tomadas con datos. Si la base de tu servidor todavía está en configuración inicial, empezá por el tutorial de creación de servidor de MU Online antes de invertir tiempo en pruebas de carga avanzadas.

Preguntas frecuentes

¿Necesito bots reales conectándose al juego, o alcanza con simular el protocolo?

Para pruebas de carga de conexión (ConnectServer y login), simular el protocolo de red directamente con un script es más eficiente y escalable que abrir cientos de clientes reales. Para probar comportamiento de gameplay (movimiento, combate, drop), se necesitan bots que emulen el protocolo del GameServer, aunque igual son más livianos que el cliente completo.

¿Cuántos jugadores simultáneos debo simular en la prueba?

Empezá por la meta realista de lanzamiento (por ejemplo, 300 CCU) y superala en un 50-100% para descubrir el margen de seguridad real. Si tu objetivo es 300 en línea, probá hasta 450-600 para saber dónde el sistema realmente se rompe.

¿La prueba de carga se puede hacer en el servidor de producción?

No se recomienda. Usá un entorno de staging con hardware y configuración lo más parecidos posible al de producción. Probar en producción arriesga corromper datos reales de jugadores o causar una caída visible durante la prueba.

¿Qué exactamente debo medir durante la prueba?

Como mínimo: uso de CPU y memoria del proceso del GameServer/ConnectServer, tiempo de respuesta de login, tiempo de respuesta de cambio de mapa, número de paquetes perdidos/latencia de red y uso de conexiones de la base de datos.

¿Qué hacer con los resultados después de la prueba?

Documentá el punto exacto donde la performance se degrada (por ejemplo, 'por encima de 400 CCU la latencia de cambio de mapa supera los 2s') y usalo para dimensionar hardware, ajustar configuraciones de la base de datos (pool de conexiones) o definir un límite de cola de entrada (login queue) antes del lanzamiento oficial.

RO
Fundador y editor jefe

Rodrigo mantiene ViciadosMU desde los inicios del portal. Especialista en creación y administración de servidores de MU Online, historia del juego y la evolución de las seasons — escribió buena parte del archivo antes de 2024.

Sigue leyendo

Artículos relacionados