Pruebas de brokers

Pruebas de carga MQTT con JMeter: plugin, thread groups y resultados

Prueba la carga de un broker MQTT con Apache JMeter: instala el plugin MQTT, crea thread groups de publishers y subscribers, ejecuta sin GUI y lee resultados.

Actualizado · 9 min de lectura

Pruebas de carga MQTT con JMeter: plugin, thread groups y resultados

Apache JMeter puede hacer pruebas de carga a un broker MQTT en cuanto le añades un plugin MQTT: cada thread de JMeter se convierte en un cliente MQTT que se conecta, publica o se suscribe, y los timers, listeners y el informe HTML de JMeter hacen el resto. Si tu equipo ya usa JMeter para HTTP, así mantienes una sola herramienta, un solo formato de informe y un solo job de CI también para tus pruebas MQTT.

Esta guía instala el plugin, construye un test plan con publishers y subscribers, lo ejecuta sin GUI y explica qué miden realmente los números.

Elegir un plugin MQTT

JMeter no incluye ningún sampler MQTT. La opción más usada es emqx/mqtt-jmeter (publicado originalmente por XMeter). Añade cuatro samplers:

SamplerQué hace
MQTT ConnectAbre una conexión (TCP, SSL, WS o WSS) y la mantiene para el thread
MQTT Pub SamplerPublica en un topic con el QoS, el flag retain y el payload elegidos
MQTT Sub SamplerSe suscribe y muestrea los mensajes recibidos durante una ventana de tiempo o hasta un número de mensajes
MQTT DisConnectCierra la conexión del thread

Los samplers Pub y Sub reutilizan la conexión creada por el sampler Connect en el mismo thread. Si todavía no existe conexión, fallan de inmediato — que es justo lo que quieres ver en el informe.

Instalar JMeter y el plugin

JMeter necesita un runtime de Java (Java 8 o superior para JMeter 5.6). Descarga JMeter y copia el jar del plugin desde la página de releases del proyecto a lib/ext:

Instalar JMeter 5.6.3 y el plugin MQTT
curl -LO https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.6.3.tgz
tar xzf apache-jmeter-5.6.3.tgz

# descarga el jar más reciente de https://github.com/emqx/mqtt-jmeter/releases
cp ~/Downloads/mqtt-xmeter-*.jar apache-jmeter-5.6.3/lib/ext/

apache-jmeter-5.6.3/bin/jmeter   # abre la GUI para construir el plan

Tras reiniciar, haz clic derecho en un Thread Group → Add → Sampler y aparecerán los cuatro samplers MQTT. Usa la GUI solo para construir y depurar el plan; genera la carga real desde la línea de comandos.

Antes de lanzar carga, comprueba que host, puerto y credenciales funcionan con un único cliente en el cliente MQTT online. Una contraseña incorrecta con 500 threads produce 500 errores idénticos y ninguna información útil. Los ejemplos usan broker.connectmq.com, un endpoint compartido pensado para comprobaciones funcionales rápidas; para la ejecución de carga en sí, apunta -Jhost y las credenciales a tu propia instancia privada de broker.

Construir el test plan

Una prueba de telemetría realista tiene dos grupos de clientes: publishers que envían datos de dispositivos y subscribers que los consumen. Esta estructura da a cada publisher su propio topic y su propio subscriber (uno a uno), así mides el enrutamiento y no el fan-out:

mqtt-load.jmx — árbol del test plan
Test Plan
├── User Defined Variables: HOST, PORT, THREADS, RATE
├── Thread Group "subscribers"   threads=${THREADS}  ramp-up=30 s
│   ├── MQTT Connect           clientId prefix "jm_sub_" + random suffix
│   └── MQTT Sub Sampler       topic testmqtt/jmeter/${__threadNum}/data
├── Thread Group "publishers"    threads=${THREADS}  ramp-up=60 s  duration=600 s
│   ├── Once Only Controller
│   │   └── MQTT Connect       clientId prefix "jm_pub_" + random suffix
│   └── MQTT Pub Sampler       topic testmqtt/jmeter/${__threadNum}/data
│       └── Constant Throughput Timer   ${RATE} samples/min, all active threads
├── tearDown Thread Group → MQTT DisConnect
└── Summary Report (GUI debugging only)

Ajustes clave, sampler por sampler:

  • Variables. Define HOST como ${__P(host,broker.connectmq.com)}, PORT como ${__P(port,1883)}, etc. __P lee una propiedad pasada con -J en la línea de comandos y usa el valor por defecto si no existe, así un mismo .jmx sirve para todos los entornos.
  • MQTT Connect. Servidor ${HOST} (sin prefijo tcp://), puerto ${PORT}, protocolo TCP (o SSL con el puerto 8883, WSS con el 8084), usuario y contraseña desde propiedades y un keep alive igual al de tus dispositivos. Activa el sufijo aleatorio del client ID: dos threads con el mismo client ID se expulsarían mutuamente del broker.
  • Once Only Controller. El thread publisher se conecta solo en su primera iteración y luego repite el Pub sampler. Sin él, cada iteración abriría una conexión nueva y estarías probando la tasa de conexiones en lugar del throughput.
  • MQTT Pub Sampler. QoS 1, retain desactivado, tipo de payload "random string with fixed length" con el tamaño de tus mensajes reales (por ejemplo 256 bytes) y "Add timestamp in payload" activado para que los subscribers puedan calcular la latencia.
  • MQTT Sub Sampler. El mismo QoS, "Payload includes timestamp" activado y muestreo por "number of received messages" (por ejemplo 100). Cada muestra representa entonces un lote de mensajes e informa de su latencia.
  • Constant Throughput Timer. Su objetivo se expresa en muestras por minuto. Para 1.000 mensajes por segundo entre todos los publishers, pon 60.000 y elige "all active threads in current thread group". Colócalo como hijo del Pub sampler para que solo marque el ritmo de publicación.

${__threadNum} es el número del thread dentro de su propio grupo, así que el publisher 17 y el subscriber 17 comparten testmqtt/jmeter/17/data. Comprueba el patrón con el topic matcher si pasas a suscripciones con wildcards.

Ejecutar sin GUI y generar el informe

El modo GUI distorsiona los resultados: dibujar los listeners consume CPU del generador de carga. Ejecuta en modo no GUI, escribe las muestras en un fichero .jtl y deja que JMeter genere su dashboard HTML al final:

Ejecutar el plan desde la línea de comandos
export MQTT_USER=username MQTT_PASS=password
HEAP="-Xms1g -Xmx4g" apache-jmeter-5.6.3/bin/jmeter -n \
  -t mqtt-load.jmx \
  -Jhost=broker.connectmq.com -Jport=1883 \
  -Juser="$MQTT_USER" -Jpass="$MQTT_PASS" \
  -Jthreads=200 -Jrate=60000 \
  -l results.jtl -e -o report/

-n es el modo no GUI, -l el fichero de resultados y -e -o genera el dashboard en una carpeta vacía. El script de arranque jmeter lee la variable HEAP; auméntala cuando subas el número de threads, porque cada thread mantiene un cliente MQTT completo.

Listeners: cuáles mantener y cuáles desactivar

ListenerPara qué sirve¿Durante la carga?
View Results TreeDepurar un thread, revisar payloadsNo — desactívalo
Summary Report / Aggregate ReportRecuentos rápidos por sampler, % de errores, throughputSolo en pruebas en seco con GUI
Fichero .jtl + dashboard HTML (-e -o)Informe final: percentiles, throughput en el tiempoSí
Backend Listener (InfluxDB)Gráficas en vivo en Grafana en ejecuciones largasSí, si necesitas datos en vivo

El dashboard HTML agrupa los resultados por la etiqueta del sampler, así que dales nombres claros ("Pub QoS1 256B", "Sub batch 100"): las etiquetas son los títulos de tu informe.

Qué significan los números

JMeter muestra un "response time" para cada muestra, pero cada sampler MQTT mide algo distinto:

SamplerEl tiempo transcurrido significaQué vigilar
MQTT ConnectDesde CONNECT hasta CONNACK (incluido el handshake TLS)Errores y conexiones lentas durante el ramp-up
MQTT Pub SamplerTiempo para entregar el mensaje; con QoS 1/2 incluye la espera del acuse del brokerSi sube, hay back-pressure del broker o de la red
MQTT Sub SamplerLa ventana de muestreo que configuraste, no la latencia de entregaMensajes recibidos por muestra y latencia calculada a partir de los timestamps

Las dos cifras más importantes son el throughput de publicación (muestras Pub por segundo, en el dashboard) y la latencia extremo a extremo (el cálculo de timestamps del Sub sampler). Si los mensajes recibidos se quedan por detrás de los enviados, algo se está perdiendo o encolando; repite con QoS 1 para separar problemas de capacidad de las pérdidas de QoS 0. Tienes un análisis más detallado de percentiles y falsos cuellos de botella en interpretar resultados de benchmarks MQTT.

Los errores de conexión que aparecen justo en un número redondo de threads suelen indicar un límite del sistema operativo en el generador de carga o un límite de conexiones en el broker: consulta too many connections y busca el reason code con la herramienta de reason codes MQTT.

Escalar el generador de carga

Cada thread de JMeter es un thread de Java con su propio cliente MQTT, así que JMeter pesa más por conexión que las herramientas basadas en Erlang o Go. Límites prácticos:

  • Sube ulimit -n en el generador de carga y dale a JMeter suficiente heap.
  • Vigila la CPU del generador. Por encima del 80 % aproximadamente, tus mediciones describen a JMeter, no al broker.
  • Para más conexiones, usa el modo distribuido de JMeter (-R host1,host2) para que varias máquinas ejecuten el mismo plan, o lleva la prueba de conexiones pura a emqtt-bench y reserva JMeter para pruebas por escenarios.
  • Las versiones 2.x del plugin añaden samplers de conexión/desconexión por lotes que abren varias conexiones por thread; revisa las notas de la versión si necesitas reducir el número de threads.

Un flujo de trabajo repetible con JMeter

  1. Verifica una conexión a mano en el cliente online.
  2. Ejecuta el plan en la GUI con 2 threads y View Results Tree activado; confirma que todos los samplers funcionan.
  3. Desactiva View Results Tree, guarda y ejecuta sin GUI al 10 %, 50 %, 100 % y 150 % del pico esperado.
  4. Guarda los .jtl y dashboards de cada ejecución junto a las métricas de CPU, memoria y conexiones del broker.
  5. Sube el .jmx a tu repositorio y vuelve a ejecutarlo tras cada actualización del broker.

Observa en vivo el tráfico de tu prueba JMeter

JMeter no es el generador de carga MQTT más ligero, pero sí uno práctico cuando tu equipo ya lo conoce: planes parametrizados, timers para tasas de mensajes exactas y un informe HTML listo para usar. Mantén los samplers sencillos, ejecuta sin GUI y lee el tiempo de cada sampler por lo que realmente mide.

Preguntas frecuentes

¿JMeter soporta MQTT de serie?

No. JMeter no incluye un sampler MQTT. Necesitas un plugin como emqx/mqtt-jmeter (antes XMeter), que añade los samplers Connect, Pub, Sub y DisConnect. Copia su jar en lib/ext y reinicia JMeter.

¿Puede JMeter probar MQTT 5?

El plugin emqx/mqtt-jmeter documenta MQTT 3.1 y 3.1.1. Si tu prueba depende de funciones de MQTT 5 como reason codes, user properties o session expiry, usa una herramienta con soporte MQTT 5 como emqtt-bench o k6 con xk6-mqtt.

¿Cuántas conexiones MQTT puede abrir una máquina con JMeter?

Depende del heap, la CPU y los límites del sistema operativo, porque cada thread de JMeter mantiene una conexión MQTT. Aumenta el heap y ulimit -n, ejecuta sin GUI y usa el modo distribuido o una herramienta más ligera como emqtt-bench si necesitas decenas de miles de conexiones.