Pruebas de carga

Pruebas de esfuerzo del broker en dos bancos —por red y por bucle local— para separar el comportamiento propio del broker del entorno. A continuación: método, tablas completas y conclusiones breves.

Descargar el informe (PDF)

Los bancos

Fecha: 24 de julio de 2026 · Protocolo: MQTT 3.1.1 · Herramienta: cliente de carga propio cmd/loadtest construido sobre el códec del proyecto, sin bibliotecas MQTT de terceros.

Se probó en dos bancos para separar el comportamiento propio del broker de la influencia del entorno: red frente a bucle local, hardware modesto frente a hardware potente.

Banco A — por redBanco B — bucle local
Procesador del broker12 núcleos2× Xeon E5-2690 v4 a 2,6 GHz (28 núcleos / 56 hilos)
Memoria del broker16 GB128 GB
Dirección192.168.1.84:1883 (LAN)127.0.0.1:1883 (bucle local)
Generador de cargaMáquina aparte en la LANLa misma máquina que el broker
Puertos efímeros del cliente16 384 (por defecto)55 000 (ampliado)
Cómo leer la comparación. Los bancos no son equivalentes y responden a preguntas distintas. El banco A muestra el funcionamiento sobre una red con generador dedicado. El banco B elimina la red (latencia casi nula) y da al broker hardware potente, pero generador y broker comparten los mismos núcleos. Por eso latencia y abanico sí se comparan de tú a tú, mientras que la ingesta no: en el banco B el cliente le roba núcleos al broker.

Resumen ejecutivo

  • Latencia. Por red, la latencia de extremo a extremo «publicador → broker → suscriptor» con carga normal ronda 1 ms; por bucle local es de 73 µs (~16 veces menos, sin la red).
  • Conexiones. Por red el broker mantuvo 10 000 sesiones sin fallos (más allá topamos con el límite de puertos del cliente). En hardware potente por bucle local: 30 000 sin fallos y ~41 000 en un intento de 50 000 (el límite de una sola máquina, no del broker).
  • Ingesta. El pico por red fue de ≈277 000 mensajes/s; por bucle local la ingesta es menor (≈185 000/s) porque el generador compite con el broker por los núcleos.
  • Abanico (encaminamiento). En hardware potente el broker entregó ≈1 350 000 mensajes/s a los suscriptores (abanico ×100) frente a ≈22 000/s por red.
  • Robustez. En ningún banco el broker se cayó ni se quedó colgado. En sobrecarga, los mensajes QoS 0 hacia suscriptores rezagados se descartan de forma ordenada; el registro del broker no contiene ni un solo error en todas las pruebas.

Capacidad de conexiones simultáneas

Cada conexión es un ciclo completo CONNECT → CONNACK con autenticación; después la sesión se mantiene abierta (comprobada con PINGREQ).

Banco A — por red

ObjetivoEstablecidasFallidasEstablecimiento p50p99
10100146 ms162 ms
1001000702 ms1,12 s
1000100004,21 s9,78 s
5000500004,64 s8,59 s
10 00010 00004,92 s10,52 s
15 00014 8791217,43 s14,09 s

Banco B — bucle local (subida gradual)

ObjetivoEstablecidasFallidasEstablecimiento p50p99
100010000886 ms1,06 s
10 00010 0000903 ms1,55 s
30 00030 0000923 ms1,90 s
50 00041 2190984 ms1,90 s

Análisis

  • Por red, hasta 10 000 sin un solo fallo; los 121 fallos a 15 000 son agotamiento de los puertos efímeros del cliente (16 384). Es el límite del generador, no del broker.
  • Por bucle local, tras ampliar el rango de puertos, el broker mantuvo 30 000 sesiones sin defecto; a 50 000 quedaban vivas unas 41 000 al final del periodo de retención, porque ambos lados comparten una máquina. El registro del broker se mantuvo limpio en todo momento, sin errores.
  • Hallazgo lateral. Por bucle local, una ráfaga de conexiones demasiado brusca (1000 dials simultáneos) provoca connection refused: la cola de aceptación se desborda, porque sin retardo de red todos los SYN llegan a la vez. Una subida gradual (200 cada vez) elimina el efecto por completo. En una red, la latencia suaviza la ráfaga por sí sola.

Rendimiento de ingesta

Un conjunto de publicadores publica lo más rápido posible; se mide el ritmo de ingesta del broker.

QoS 0 · carga útil de 64 bytes

PublicadoresBanco A (red)Banco B (bucle local)
10271 006/s185 012/s
100236 422/s101 457/s
500103 546/s125 324/s

La ingesta es mayor por red, no porque el broker del banco A sea más rápido, sino porque allí el generador corre en una máquina aparte. Por bucle local, cliente y broker comparten los mismos núcleos, lo que limita el ritmo conjunto.

QoS 1 (con confirmación PUBACK) · 64 B

PublicadoresBanco A (red)Banco B (bucle local)
1010 292/s63 606/s
10022 085/s48 983/s

El cliente de prueba de QoS 1 es síncrono (espera un PUBACK tras cada mensaje), así que queda limitado por el ida y vuelta. Por bucle local ese ida y vuelta es casi nulo, de ahí la mejora de unas 6 veces. Esto muestra con claridad que las cifras de QoS 1 las fija la latencia de red, no el broker.

Barrido de tamaños de mensaje · QoS 0 · 50 publicadores

TamañoBanco A (red)Banco B (bucle local)
64 B277 198/s · 17,7 MB/s101 961/s · 6,5 MB/s
256 B124 997/s · 32,0 MB/s102 029/s · 26,1 MB/s
1024 B38 458/s · 39,4 MB/s102 151/s · 104,6 MB/s

Dos techos distintos:

  • Por red topamos con el enlace en torno a 40 MB/s: al crecer el mensaje, los msg/s caen mientras los MB/s se mantienen cerca del límite.
  • Por bucle local el enlace es enorme, así que el número de mensajes se mantiene (~102 000/s con 50 conexiones) y el volumen sube a 104,6 MB/s. Aquí el cuello de botella es el procesamiento por mensaje (procesador), no los bytes.

Entrega de extremo a extremo

Se incrusta una marca de tiempo en el cuerpo del mensaje; se mide la entrega real y la latencia de extremo a extremo. Abanico significa entrega a cada suscriptor cuyo filtro coincida.

Banco A — por red

EscenarioPublicaciónEntregamedia / p50 / p99
10 sus. / 10 pub. / 100 msg/s — normal986/s9863/s1,17 / 1,0 / 3,6 ms
100 sus. / 10 pub. / sin freno261 551/s22 351/s780 / 453 / 678 ms
100 sus. / 10 pub. / 500 msg/s4934/s12 150/s1,87 / 1,77 / 2,83 s
1000 sus. / 5 pub. / 100 msg/s494/s178 961/s2,29 s / 480 / 952 ms

Banco B — bucle local

EscenarioPublicaciónEntregamedia / p50 / p99
10 sus. / 10 pub. / 100 msg/s — normal987/s9867/s73 / ~0 / 555 µs
100 sus. / 10 pub. / sin freno47 557/s1 353 431/s514 / 135 / 251 ms
100 sus. / 10 pub. / 500 msg/s3608/s360 834/s17,1 / 10,5 / 71,6 ms
1000 sus. / 5 pub. / 100 msg/s494/s183 746/s4,73 / 4,54 / 15,1 ms

Análisis

  • Latencia con carga normal: 1,17 ms por red frente a 73 µs por bucle local. La diferencia es el trayecto de red.
  • Encaminamiento bajo carga: la máquina potente entregó ≈1,35 millones de mensajes/s a los suscriptores (abanico ×100), dos órdenes de magnitud por encima del banco de red (22 mil/s), donde tanto el broker como el enlace son pequeños.
  • En escenarios de gran abanico el generador se convierte también en cuello de botella (todos los suscriptores en un proceso y una máquina), así que las cifras pico de entrega son una cota inferior de lo que el broker puede dar.

Cara a cara

IndicadorBanco A — red (12 núcleos)Banco B — bucle local (28 núcleos)
Conexiones sin fallos10 00030 000
Pico de conexiones14 879 (límite del cliente)~41 000 (límite de una máquina)
Ingesta QoS 0 (64 B), pico271 006/s185 012/s
Ingesta QoS 1 (64 B), pico22 085/s63 606/s
Techo de volumen≈40 MB/s (enlace)≈105 MB/s (procesador)
Latencia (normal), mediana1,0 ms~0 (73 µs de media)
Entrega con abanico, pico22 351/s1 353 431/s
Errores en el registro del brokerningunoninguno

Salvedades metodológicas

  • El ritmo de ingesta no es directamente comparable entre bancos: en el banco B generador y broker comparten núcleos; en el banco A el generador es una máquina aparte.
  • En cada banco la carga procede de una sola máquina cliente; en algunos escenarios (gran abanico, decenas de miles de conexiones) el cuello de botella es esa máquina y no el broker.
  • El cliente de prueba de QoS 1 es síncrono, así que las cifras de QoS 1 subestiman el potencial del broker.
  • No se registraron las métricas de sistema del broker (procesador y memoria durante las pruebas); el estado del servidor se deduce de su registro (sin errores) y del comportamiento del lado cliente.

Reproducir

Cada prueba se lanza desde un único binario loadtest; abajo están las órdenes de los tres modos.

go build -o loadtest ./cmd/loadtest

# Capacidad de conexiones (subida gradual frente a la cola de aceptación)
./loadtest -addr HOST:1883 -user myelx -pass *** \
    -mode conn -levels 1000,10000,30000,50000 -hold 3s -dial-concurrency 200

# Rendimiento de ingesta
./loadtest -addr HOST:1883 -user myelx -pass *** \
    -mode pub -pubs 10 -qos 0 -payload 64 -duration 10s

# Entrega de extremo a extremo y latencia
./loadtest -addr HOST:1883 -user myelx -pass *** \
    -mode pubsub -subs 10 -pubs 10 -qos 0 -rate 100 -payload 64 -duration 10s