Fundamentos de MQTT

Latencia MQTT explicada: qué afecta al tiempo de ida y vuelta y cómo medirlo

¿De dónde sale la latencia MQTT? Esta guía desglosa los retardos de red, TLS, QoS y procesamiento del broker, y te da un script en Python para medir el tiempo de ida y vuelta contra broker.connectmq.com.

Ilustración de la latencia MQTT como un cronómetro que mide un mensaje que viaja desde un dispositivo hasta un broker en la nube y vuelve
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

La latencia MQTT es el tiempo que transcurre entre que un publicador envía un mensaje y un suscriptor lo recibe, y en la mayoría de sistemas IoT está dominada por factores ajenos al propio protocolo. Esta guía desglosa cada componente del tiempo de ida y vuelta, explica qué ajustes importan de verdad y te da un pequeño script en Python para medir la latencia desde tu propia red contra un broker real.

Qué significa "latencia" en MQTT

La palabra se usa para varias mediciones distintas, así que sé preciso antes de optimizar:

  • Latencia en un sentido: del publicador al suscriptor. Es difícil de medir con exactitud porque los dos relojes están en máquinas distintas.
  • Tiempo de ida y vuelta (RTT): un cliente publica en un topic al que también está suscrito y mide cuánto tarda en volver el mensaje. Un solo reloj, así que el número es fiable. Es lo que mide el script de más abajo.
  • Latencia de conexión: tiempo desde que se abre el socket hasta que se recibe el CONNACK. Relevante para dispositivos que se despiertan, se conectan, publican y vuelven a dormir.
  • Latencia de confirmación: tiempo desde el PUBLISH hasta el PUBACK con QoS 1, que te indica cuándo el broker ha asumido la responsabilidad del mensaje.

Para dispositivos que mantienen una conexión abierta (el patrón normal en MQTT), el tiempo de ida y vuelta es el número individual más útil.

Los componentes de la latencia MQTT

Un mensaje que va de un sensor a un dashboard pasa por varias etapas. Cada una añade retardo:

Etapa Qué ocurre Influencia típica Palanca principal
Pila del cliente La biblioteca encola, serializa y escribe en el socket Pequeña, pero grande en microcontroladores ocupados Bucle no bloqueante, evitar llamadas largas a delay()
Red de última milla Acceso Wi-Fi, celular, satélite A menudo la parte mayor y más variable Mejor enlace, señal celular, gateway cableado
Ruta por internet Enrutamiento hasta la región del broker Crece con la distancia física Región del broker cercana a los dispositivos
TLS Cifrado por paquete, handshake por conexión El handshake cuesta viajes de ida y vuelta extra una vez; el coste por paquete es pequeño Mantener conexiones de larga duración
Handshake de QoS PUBACK o flujo de 4 pasos de QoS 2 No retrasa mucho la entrega, pero limita el throughput Elegir QoS según el tipo de dato
Procesamiento del broker Autenticación, coincidencia de topics, fan-out Normalmente pequeño en un broker sano Evitar fan-outs enormes y topics calientes
Lado del suscriptor El mismo camino a la inversa, más el procesamiento de la aplicación Refleja el lado del publicador Callbacks ligeros

Distancia de red

La luz en la fibra es rápida, pero no instantánea, y las rutas reales no son líneas rectas. Un dispositivo en Estambul que habla con un broker en otro continente siempre tendrá una base más alta que uno que habla con un broker de su propia región. Ningún ajuste del protocolo puede eliminar esto; solo la ubicación del broker.

Sobrecarga de TLS

El handshake TLS añade viajes de ida y vuelta al abrir la conexión. Después, el cifrado simétrico cuesta muy poco en CPUs modernas y solo una cantidad moderada en chips como el ESP32. Como los clientes MQTT suelen permanecer conectados durante horas o días, TLS afecta sobre todo a la latencia de conexión, no a la latencia de los mensajes en régimen estable. Por eso "TLS es lento" rara vez es un buen motivo para usar el puerto 1883; consulta puertos MQTT explicados para ver las ventajas e inconvenientes.

Nivel de QoS

Es la parte peor entendida. Con QoS 0, el broker reenvía de inmediato. Con QoS 1, el broker también reenvía de inmediato al recibir el mensaje, y el PUBACK vuelve en paralelo, así que en un enlace sano la latencia de entrega es similar a la de QoS 0. QoS 2 añade un handshake de cuatro pasos; según la implementación del broker, el reenvío puede producirse tras el primer o el segundo paso. El mayor efecto de un QoS más alto está en el throughput y en lo que ocurre cuando se pierden paquetes: las retransmisiones añaden latencia cuando la red se comporta mal. La guía de niveles de QoS de MQTT cubre los flujos en detalle.

Nagle, buffers y el bucle del cliente

Algunas pilas retrasan las escrituras pequeñas para combinarlas. Muchas bibliotecas MQTT desactivan el algoritmo de Nagle, pero puede que las pilas embebidas y los sockets personalizados no lo hagan. En microcontroladores, un bucle principal que llama a client.loop() solo una vez por segundo añade hasta un segundo de latencia a los mensajes entrantes, por rápida que sea la red.

Keep-alive y reconexiones

El keep-alive no afecta a la latencia en una conexión sana, pero decide lo rápido que se detecta una conexión muerta. Un enlace caído en silencio con un keep-alive de 300 segundos puede suponer minutos hasta que el cliente se reconecta, y todos los mensajes de ese intervalo llegan tarde.

Mide tú mismo la latencia MQTT

El script siguiente se conecta al servidor MQTT público gratuito broker.connectmq.com, pensado para pruebas y prototipos, se suscribe a un topic único, publica en él mensajes con marca de tiempo y calcula estadísticas de ida y vuelta. Se mantiene por debajo del límite del servidor público de 10 mensajes por segundo por cliente enviando dos por segundo.

# mqtt_rtt.py - mide la latencia de ida y vuelta de MQTT
# pip install "paho-mqtt>=2.0"
import json
import statistics
import sys
import threading
import time
import uuid

import paho.mqtt.client as mqtt

HOST = "broker.connectmq.com"
USE_TLS = "--tls" in sys.argv
PORT = 8883 if USE_TLS else 1883
QOS = 1
SAMPLES = 50
INTERVAL = 0.5  # segundos entre publicaciones (2 msg/s)

run_id = uuid.uuid4().hex[:8]
topic = f"connectmq/demo/{run_id}/rtt"
rtts = []
subscribed = threading.Event()
done = threading.Event()


def on_connect(client, userdata, flags, reason_code, properties):
    print(f"Connected to {HOST}:{PORT} -> {reason_code}")
    client.subscribe(topic, qos=QOS)


def on_subscribe(client, userdata, mid, reason_code_list, properties):
    subscribed.set()


def on_message(client, userdata, msg):
    received = time.perf_counter()
    data = json.loads(msg.payload)
    rtts.append((received - data["t"]) * 1000.0)
    if len(rtts) >= SAMPLES:
        done.set()


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"rtt-{run_id}")
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message
if USE_TLS:
    client.tls_set()  # usa el almacén de CA del sistema

t0 = time.perf_counter()
client.connect(HOST, PORT, keepalive=60)
client.loop_start()
if not subscribed.wait(10):
    sys.exit("Subscribe timed out")
print(f"Connect + subscribe took {(time.perf_counter() - t0) * 1000:.1f} ms")

for seq in range(SAMPLES):
    payload = json.dumps({"seq": seq, "t": time.perf_counter()})
    client.publish(topic, payload, qos=QOS)
    time.sleep(INTERVAL)

done.wait(10)
client.loop_stop()
client.disconnect()

if not rtts:
    sys.exit("No messages received")

rtts.sort()
p95 = rtts[int(len(rtts) * 0.95) - 1]
print(f"samples={len(rtts)} lost={SAMPLES - len(rtts)}")
print(f"min={rtts[0]:.1f} ms  median={statistics.median(rtts):.1f} ms  "
      f"p95={p95:.1f} ms  max={rtts[-1]:.1f} ms")

Ejecútalo dos veces y compara:

python mqtt_rtt.py         # TCP sin cifrar en 1883
python mqtt_rtt.py --tls   # TLS en 8883

Cómo leer los resultados

  1. El mínimo se aproxima al camino en el mejor caso: red más broker sin nada en medio. Es tu suelo.
  2. La mediana es lo que experimentan normalmente los usuarios.
  3. El p95 y el máximo revelan el jitter causado por reintentos de Wi-Fi, la planificación de la red celular o enlaces congestionados. Para bucles de control y alarmas, importan más que la mediana.
  4. Connect + subscribe muestra el coste del handshake TLS. Es de esperar que sea notablemente mayor con --tls, mientras que la mediana por mensaje se mantiene cerca de la de la ejecución sobre TCP sin cifrar.
  5. Las muestras perdidas con QoS 1 suelen significar que el script terminó antes de que llegaran los mensajes rezagados o que la conexión se cayó. Revisa la consola en busca de desconexiones.

Ejecuta la prueba desde donde viven realmente tus dispositivos (la red de planta, un módem celular, un router doméstico), no solo desde tu oficina. La diferencia suele ser el hallazgo más valioso.

Formas prácticas de reducir la latencia MQTT

  1. Mantén las conexiones abiertas. Conéctate una vez y publica muchas. Reconectar por cada mensaje paga cada vez el handshake TCP y TLS.
  2. Elige una región del broker cercana a tus dispositivos. La distancia marca el suelo.
  3. Elige el QoS según el tipo de dato. La telemetría de alta frecuencia, en la que la siguiente muestra sustituye a la anterior, puede usar QoS 0; los comandos y las alarmas merecen QoS 1.
  4. Mantén los payloads compactos. Los documentos JSON grandes tardan más en enviarse por enlaces lentos. Valora codificaciones binarias para datos de alta frecuencia y los topic aliases de MQTT 5 para acortar nombres de topic repetidos.
  5. Atiende el bucle del cliente a menudo. En Arduino o ESP32, llama a loop() en cada iteración y evita los retardos bloqueantes.
  6. Ajusta el keep-alive para detectar rápido los enlaces muertos (de 30 a 60 segundos es habitual) sin desperdiciar ancho de banda.
  7. Evita saltos innecesarios. Cada bridge, gateway o relé de Node-RED en el camino añade su propio procesamiento y sus colas.
  8. Haz que los callbacks del suscriptor sean rápidos. Pasa el trabajo pesado a un hilo de trabajo o a una cola para no bloquear el bucle de red.

Solución de problemas de latencia alta o irregular

Síntoma Causa probable Qué revisar
RTT mínimo alto Distancia al broker o red de acceso lenta Ping y traceroute al host del broker
Buena mediana, p95 pésimo Reintentos de Wi-Fi, planificación celular Prueba en un enlace cableado para comparar
La latencia crece con el tiempo El suscriptor no da abasto, los mensajes se encolan Duración de los callbacks y recuento de mensajes en vuelo
Huecos periódicos de varios segundos Código bloqueante en el bucle del cliente sleep largos o E/S síncrona en los callbacks
Picos solo al reconectar Handshake TLS más reanudación de sesión Estabilidad de la conexión y keep-alive
Limitación en el servidor público Límite de 10 msg/s por cliente Reduce la tasa de publicación o usa un broker privado

De la medición a producción

El servidor público es compartido, así que toma sus cifras como indicativas de tu ruta de red y no como un benchmark. Para el tráfico de producción, un broker MQTT gestionado como ConnectMQ te da un endpoint privado y autenticado en el 8883 y el 8084 sin los límites de tasa del público; los detalles de los planes están en la guía de brokers MQTT en la nube. Para repetir la prueba contra tu propio broker de ConnectMQ, añade client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD"), establece el client ID en YOUR_CLIENT_ID y ejecuta con --tls. Para un contexto más amplio sobre el protocolo, consulta el tutorial de MQTT y cómo funciona MQTT.

Empieza con ConnectMQ

Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y apunta el script de latencia hacia él con dos líneas. El cliente integrado en el navegador y el explorador de topics en vivo de ConnectMQ te ayudan a ver exactamente cuándo llega cada mensaje.

Preguntas frecuentes

¿Qué es una buena latencia MQTT?

Depende de la distancia y de la red de acceso. Compara tu RTT mínimo con un ping de red normal al host del broker; si MQTT añade solo un poco por encima, el broker no es tu cuello de botella.

¿QoS 1 hace que MQTT sea más lento que QoS 0?

En un enlace sano, la latencia de entrega es similar porque el broker reenvía antes de que se complete el PUBACK. QoS 1 añade sobrecarga sobre todo cuando se pierden paquetes y hay que reenviarlos.

¿TLS aumenta la latencia MQTT?

TLS añade tiempo de handshake al conectar, pero en una conexión de larga duración la sobrecarga por mensaje es pequeña. Mantener las conexiones abiertas es la mejor forma de minimizar su impacto.

¿Por qué medir la ida y vuelta en lugar de la latencia en un sentido?

La ida y vuelta usa un solo reloj, así que evita los errores de los relojes no sincronizados entre las máquinas del publicador y del suscriptor.

Artículos relacionados

¿Quién inventó MQTT? La historia, de los oleoductos al IoT

MQTT lo inventaron en 1999 Andy Stanford-Clark, de IBM, y Arlen Nipper, de Arcom, para monitorizar oleoductos vía satélite. Sigue su camino hacia el open source, OASIS, ISO y los brokers MQTT gestionados en la nube de hoy.

8 min de lectura

Por qué tu cliente MQTT se desconecta constantemente (y cómo solucionarlo)

Los bucles de reconexión son uno de los problemas más habituales de MQTT. Conoce las cinco causas típicas, desde los client ID duplicados hasta los timeouts de keep alive y los paquetes demasiado grandes, y sigue un flujo de diagnóstico que localiza la tuya.

9 min de lectura

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.