← Índice del curso

Internet de las Cosas · Tema 26

Broker, tópicos y suscripciones

El tema anterior presentó el modelo: alguien publica, alguien se suscribe y el broker reparte. Ahora miramos el reparto de cerca. Cómo se escriben los nombres de los tópicos, qué reglas tienen los filtros, qué ocurre cuando dos suscripciones coinciden y cuánto trabajo le da al broker cada mensaje que entra. Son detalles pequeños con consecuencias grandes en una flota.

01 · Punto de partida

El centro del sistema

En una arquitectura con MQTT, el broker es el único componente por el que pasa todo. Si falla, todo falla; si está mal configurado, cualquiera puede leer todo; si se queda corto, los mensajes se demoran o se pierden para todos a la vez. Es, a la vez, el componente más simple de entender (reparte mensajes según tópicos) y el más importante de acertar.

Este tema recorre cuatro cosas que determinan si un sistema MQTT escala o se rompe: lo que el broker hace por vos, las reglas de los nombres de tópico y de los filtros de suscripción (que tienen más sutileza de la que parece), cómo se instala y se protege, y cómo se calcula cuánta carga soporta.

Los números del laboratorio son un modelo con valores didácticos, no mediciones de un broker concreto; los de capacidad cambian mucho con la configuración y el hardware.

02 · Responsabilidades

Qué hace un broker

Lo que se ve desde afuera es el reparto de mensajes, pero un broker hace bastante más. Conviene tener la lista a mano, porque cada ítem es una decisión de diseño o una posible falla.

Funciones de un broker MQTT y la decisión que implica cada una.
FunciónQué haceDecisión o riesgo
Aceptar conexionesMantiene un socket TCP abierto por clienteCuántas conexiones soporta; memoria por conexión
AutenticarVerifica usuario y clave o certificado del clienteUna credencial por dispositivo; sin acceso anónimo
AutorizarDecide en qué tópicos puede publicar y suscribirse cada clienteListas de acceso por tópico; sin ellas, un equipo ve toda la flota
Registrar suscripcionesGuarda qué filtros pidió cada clienteMemoria; suscripciones que se acumulan
Enrutar y reenviarCompara cada publicación con los filtros y copia el mensaje a cada suscriptorEl reparto (fan-out) es el costo principal
Guardar mensajesRetiene el último valor de un tópico y encola mensajes para clientes desconectadosMemoria y disco; límites de cola (tema 28)
Gestionar sesiones y garantíasLleva cuenta de confirmaciones, reenvíos y calidad de servicioTrabajo y estado por cliente (tema 28)
Publicar la última voluntadAvisa que un cliente se cayó sin despedirseÚtil para detectar dispositivos mudos (tema 28)
Informar su estadoPublica estadísticas en tópicos reservados $SYS/… (conexiones, mensajes, memoria)Monitorear el propio broker

Una propiedad que conviene recordar: el broker no mira el contenido de los mensajes. Para él, la carga es una secuencia de bytes que entrega tal cual. No valida el JSON ni transforma nada. Solo mira el tópico, por eso los tópicos importan tanto y las cargas se validan en los extremos.

03 · Direcciones de los mensajes

Nombres de tópico

Un nombre de tópico es una cadena de texto con niveles separados por /. El estándar fija reglas mínimas, y la práctica agrega recomendaciones para evitar problemas futuros.

Reglas del estándar y recomendaciones para los nombres de tópico.
AspectoLo que dice el estándarRecomendación
Codificación y largoTexto UTF-8, hasta 65.535 bytes, sin el carácter nulo y con al menos un carácterCortos: cada byte del tópico viaja en cada publicación
MayúsculasDistingue mayúsculas de minúsculas: Casa y casa son tópicos distintosTodo en minúsculas
SeparadorLa barra / separa niveles; los niveles vacíos son válidosNo dejar niveles vacíos ni barra inicial: /casa tiene un primer nivel vacío
Comodines al publicarProhibidos: + y # no pueden estar en el nombre de un tópico publicado—
Tópicos reservadosLos que empiezan con $ son del broker (por ejemplo, $SYS)No usarlos para datos propios
CaracteresCualquier carácter UTF-8 es válidoSolo letras ASCII, números, guion y guion bajo: sin espacios, tildes ni símbolos
Ejemplos de nombres de tópico mejorables y su versión recomendada.
TópicoProblemaMejor
/casa/Cámara 07/TemperaturaBarra inicial (primer nivel vacío), mayúsculas, espacio y tildecasa/camara07/temperatura
casa/camara07/temperatura/Barra final (último nivel vacío): es un tópico distinto del anteriorcasa/camara07/temperatura
datosUn solo nivel para todo: no se puede filtrar por dispositivo ni por magnitudcasa/camara07/temperatura
camara07 (el identificador y el dato mezclados)Cada dato nuevo exige un tópico con otro formatocasa/camara07/estado/bateria
casa/camara07/lectura/2026-11-07T14:32Un tópico distinto por cada lectura: explosión de tópicosUn tópico fijo; el momento va en la carga

El último ejemplo es una trampa clásica. Un tópico es una dirección, no un dato. Si el tópico cambia con cada mensaje (porque lleva la hora o un contador), el broker acumula miles de tópicos distintos, las suscripciones con comodines se vuelven pesadas y los mensajes retenidos se llenan de basura. La información variable va en la carga; el tópico se mantiene estable. El diseño completo del esquema es el tema 29.

04 · Reglas de coincidencia

Filtros y comodines, con todas sus reglas

En el tema anterior viste los dos comodines. Las reglas completas tienen algunos detalles que sorprenden y conviene dominar, porque un filtro mal entendido recibe de más o de menos sin avisar:

  • + ocupa un nivel entero. No puede mezclarse con texto: casa/te+ es un filtro inválido. Y no coincide con un nivel ausente.
  • # debe ser el último nivel y estar solo. casa/#/x es inválido. Coincide con cualquier cantidad de niveles que sigan, incluido el nivel padre: casa/# recibe casa/living/temperatura pero también casa a secas.
  • Los tópicos que empiezan con $ no se alcanzan con un comodín en el primer nivel. Suscribirse a # no entrega los mensajes de $SYS/…; hay que pedirlos explícitamente ($SYS/#).
  • La coincidencia es exacta y distingue mayúsculas en los niveles sin comodín.
  • Los niveles vacíos cuentan: casa//temperatura tiene tres niveles, el del medio vacío.

El programa de este tema implementa esas reglas y las prueba con once casos. Ejecutalo y fijate en dos resultados que contradicen la intuición: casa/+ no recibe casa/living/temperatura (tiene un nivel de más), y # no recibe $SYS/broker/uptime.

Un criterio de diseño importante: los filtros se evalúan para cada mensaje publicado contra todas las suscripciones (los brokers usan estructuras de árbol que lo hacen eficiente, pero el costo existe). Y un filtro demasiado amplio, como # en un servicio de producción, convierte a ese suscriptor en el destinatario de todo el tráfico de la flota. Suscribite a lo que necesitás, no a todo.

05 · Quién recibe qué

Las suscripciones

Un cliente se suscribe con un paquete SUBSCRIBE que lleva una o varias parejas de filtro y calidad de servicio máxima. El broker responde con un SUBACK que indica, para cada filtro, la calidad concedida o un código de fallo (el broker puede rechazar una suscripción por permisos). El cliente debe revisar el SUBACK: suponer que la suscripción se hizo y no recibir nunca nada, por un permiso denegado, es un error frecuente. Para cancelar se envía un UNSUBSCRIBE.

Tres situaciones de las suscripciones merecen atención:

  • Suscripciones traslapadas. Si un cliente se suscribe a casa/# y a casa/+/temperatura, un mensaje de temperatura coincide con las dos. El estándar permite al broker entregarle una copia por cada suscripción que coincida (o una sola con la calidad más alta). El firmware debe estar preparado para duplicados y, mejor, evitar los traslapes.
  • Suscripciones y reconexión. Si la sesión no es persistente (tema 28), las suscripciones se pierden al desconectarse, y el cliente debe volver a suscribirse en cada conexión. Es la causa del clásico «reconecta pero no recibe nada»: se reconectó pero se olvidó de suscribirse de nuevo. La buena práctica es suscribirse dentro del código de conexión, no una sola vez al arrancar.
  • Suscripciones compartidas (MQTT 5, $share/grupo/filtro). Varios clientes de un mismo grupo comparten una suscripción, y cada mensaje llega a uno solo de ellos. Sirve para repartir el trabajo entre varias instancias de un servicio (por ejemplo, cuatro procesos que guardan lecturas en la base de datos) sin que todos reciban todo.

Otra regla de higiene: el dispositivo se suscribe solo a su propio tópico de comandos, no a filtros amplios. Es más barato (menos tráfico entrante), más seguro (una lista de acceso que solo lo permite) y más fácil de razonar.

06 · Instalación y protección

Dónde corre el broker y cómo se protege

Dónde ubicar el broker.
UbicaciónVentajasInconvenientes
En el borde (en el edificio o la planta)Funciona sin Internet; latencia mínima; los datos sensibles no salenHay que operarlo; un solo sitio es un punto de falla
En la nube (propio o administrado)Disponible desde cualquier lugar; escala; lo opera otroDepende de Internet; costo mensual; los datos viajan
Borde y nube conectados con un puente (bridge)Lo local sigue funcionando si cae Internet; la nube recibe lo que correspondaMás piezas; hay que decidir qué tópicos cruzan y en qué sentido
Un clúster de brokersAlta disponibilidad y cientos de miles de conexionesComplejidad de operación; solo para escalas grandes

Una configuración mínima segura de Mosquitto, con las piezas ya vistas: un puerto con TLS, usuarios obligatorios, listas de acceso y límites. Es un archivo de configuración, no un programa:

# mosquitto.conf
listener 8883
cafile   /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/broker.crt
keyfile  /etc/mosquitto/certs/broker.key

allow_anonymous false                 # nadie entra sin credencial
password_file   /etc/mosquitto/passwd
acl_file        /etc/mosquitto/acl

max_connections       20000           # tope de clientes simultáneos
message_size_limit    1024            # bytes por mensaje
max_queued_messages   1000            # por cliente desconectado, para no llenar la memoria

# /etc/mosquitto/acl
pattern write casa/%u/#               # cada dispositivo publica solo bajo su propio nombre de usuario
pattern read  casa/%u/comandos        # y solo lee sus comandos

user panel
topic read casa/#                     # el panel lee todo, no escribe nada

El truco de las listas es el patrón con el nombre de usuario (%u): una sola regla sirve para toda la flota, porque cada dispositivo solo puede publicar en un tópico que lleve su propio nombre. Un dispositivo comprometido queda confinado a lo suyo. Los nombres de las opciones corresponden a Mosquitto; otros brokers usan otros archivos o consolas, pero las ideas son las mismas.

07 · Capacidad

Dimensionar el broker

Cuatro números describen la carga de un broker y se pueden calcular con aritmética simple:

  • Mensajes que entran por segundo = dispositivos ÷ intervalo de publicación. Diez mil dispositivos que publican cada 60 segundos son 167 mensajes por segundo.
  • Mensajes que salen por segundo = entrada × suscriptores por mensaje. Es el fan-out o reparto. Con tres suscriptores por mensaje, esos 167 se vuelven 500 que salen.
  • Ancho de banda = mensajes por segundo × tamaño del mensaje con sus encabezados (109 bytes en el ejemplo del modelo). Casi siempre es modesto: unos pocos Mbit/s para decenas de miles de mensajes.
  • Memoria = conexiones × lo que cuesta cada una, más las suscripciones, las sesiones y los mensajes encolados o retenidos. En el modelo, unos 20 KB por cliente conectado: 10.000 dispositivos son cerca de 200 MB.

Lo que más sorprende al calcular es que el límite casi siempre lo pone la salida, no la entrada: un broker recibe poco y reparte mucho. Y que la carga es muy sensible a dos decisiones de diseño que se toman en otro lado: cada cuánto publican los dispositivos y cuántos servicios se suscriben a cada tópico. Pasar de publicar cada 60 s a cada 10 s multiplica todo por 6; pasar de 3 a 10 suscriptores multiplica la salida por 3,3.

También hay límites que no son de potencia: el número máximo de conexiones del sistema operativo (descriptores de archivo), el tamaño máximo de mensaje, la cantidad de mensajes en vuelo por cliente y el largo de las colas de los clientes lentos. Un broker bien configurado los fija a propósito, y bien monitoreado (con los tópicos $SYS) avisa antes de saturarse.

08 · Analogía con programación

Probar filtros y dimensionar en Python

El programa tiene dos partes. La primera implementa las reglas completas de coincidencia: el comodín + de un nivel, el # que incluye al nivel padre, la exclusión de los tópicos $, la distinción de mayúsculas y los niveles vacíos, junto con un validador de filtros. Se prueban once combinaciones y cuatro filtros. La segunda calcula la carga de un broker para cinco flotas distintas (mensajes de entrada y salida por segundo, ancho de banda y memoria) y decide si lo soportan tres tamaños de instalación: una Raspberry Pi, un servidor virtual chico y un servicio administrado.

Python en tu navegador. Los bloques son editables: cambiá los valores y presioná «Ejecutar Python». La primera vez tarda unos segundos en cargar.

# ---------- Parte 1: las reglas de los filtros de suscripción ----------
def coincide(filtro, topico):
    f, t = filtro.split("/"), topico.split("/")
    if t[0].startswith("$") and f[0] in ("+", "#"):
        return False                         # los tópicos de sistema ($SYS) no se alcanzan con comodines iniciales
    for i, nivel in enumerate(f):
        if nivel == "#":
            return True                      # # acepta todo lo que sigue, incluido el nivel padre
        if i >= len(t):
            return False
        if nivel != "+" and nivel != t[i]:
            return False                     # + acepta un nivel cualquiera; el resto debe ser idéntico
    return len(f) == len(t)


def filtro_valido(filtro):
    niveles = filtro.split("/")
    for i, nivel in enumerate(niveles):
        if "#" in nivel and (nivel != "#" or i != len(niveles) - 1):
            return False                     # # solo como último nivel y solo
        if "+" in nivel and nivel != "+":
            return False                     # + ocupa un nivel entero
    return bool(filtro)


pruebas = [
    ("casa/+/temperatura", "casa/living/temperatura"),
    ("casa/+/temperatura", "casa/living/sala/temperatura"),
    ("casa/+", "casa/living/temperatura"),
    ("casa/#", "casa/living/temperatura"),
    ("casa/#", "casa"),
    ("+/temperatura", "casa/temperatura"),
    ("#", "casa/x"),
    ("#", "$SYS/broker/uptime"),
    ("$SYS/#", "$SYS/broker/uptime"),
    ("Casa/#", "casa/x"),
    ("casa//temperatura", "casa//temperatura"),
]
for filtro, topico in pruebas:
    print(f"filtro {filtro:<22} tópico {topico:<30} -> {'recibe' if coincide(filtro, topico) else 'no recibe'}")
print()
for filtro in ("casa/+/temperatura", "casa/#/x", "casa/te+", "casa/#"):
    print(f"¿{filtro!r} es un filtro válido?  {filtro_valido(filtro)}")

# ---------- Parte 2: dimensionar el broker ----------
PUBLISH_BYTES = 1 + 1 + 2 + 25 + 40 + 40         # tipo, longitud, tópico de 25 caracteres, carga de 40 y encabezados de red
KB_POR_CONEXION = 20                             # memoria del broker por cliente conectado (estimación)
SERVICIOS = 20                                   # paneles, archivos y reglas que también están conectados
INSTANCIAS = {                                   # (mensajes por segundo, RAM en MB)
    "Raspberry Pi": (5_000, 800),
    "Servidor virtual chico": (20_000, 3_000),
    "Servicio administrado": (200_000, 50_000),
}


def carga(dispositivos, intervalo_s, suscriptores_por_mensaje):
    entrada = dispositivos / intervalo_s
    salida = entrada * suscriptores_por_mensaje
    memoria_mb = (dispositivos + SERVICIOS) * KB_POR_CONEXION / 1024
    return entrada, salida, entrada * PUBLISH_BYTES * 8 / 1e6, salida * PUBLISH_BYTES * 8 / 1e6, memoria_mb


def veredicto(entrada, salida, memoria_mb, instancia):
    maximo, ram = INSTANCIAS[instancia]
    if memoria_mb > ram or entrada + salida > maximo:
        return "no alcanza"
    return "con margen" if entrada + salida < 0.5 * maximo else "al límite"


print()
print("dispositivos  cada   suscriptores   entrada     salida   Mbit/s (ent/sal)   RAM       Pi            servidor chico   administrado")
for dispositivos, intervalo, subs in ((100, 60, 3), (1_000, 60, 3), (10_000, 60, 3), (10_000, 10, 5), (100_000, 60, 3)):
    e, s, mbe, mbs, mem = carga(dispositivos, intervalo, subs)
    celdas = [veredicto(e, s, mem, n) for n in INSTANCIAS]
    print(f"{dispositivos:>11,} {intervalo:>4} s {subs:>10} {e:>8,.0f}/s {s:>8,.0f}/s {mbe:>7.2f} / {mbs:<7.2f} {mem:>6,.0f} MB   {celdas[0]:<12} {celdas[1]:<16} {celdas[2]}")

Resultado con los valores iniciales. Los filtros: casa/+/temperatura recibe casa/living/temperatura pero no casa/living/sala/temperatura; casa/+ no recibe un tópico de tres niveles; casa/# recibe los de cualquier profundidad y también casa; # recibe casa/x pero no $SYS/broker/uptime (que sí recibe $SYS/#); Casa/# no recibe casa/x (distingue mayúsculas); y casa//temperatura coincide con sí mismo. Los filtros casa/#/x y casa/te+ son inválidos. En la capacidad: 100 dispositivos cada 60 s con 3 suscriptores son 2 mensajes por segundo de entrada y 5 de salida (2 MB de memoria); 1000, 17 y 50 (20 MB); 10.000, 167 y 500 (196 MB); las tres instalaciones lo soportan con margen. Con 10.000 dispositivos cada 10 s y 5 suscriptores: 1000 de entrada y 5000 de salida, y la Raspberry Pi ya no alcanza (el servidor chico y el administrado sí). Con 100.000 cada 60 s y 3 suscriptores: 1667 y 5000 por segundo, 1954 MB, y la Raspberry Pi tampoco alcanza.

Tres lecciones. Una: las reglas de los comodines tienen excepciones que contradicen la intuición, y lo único seguro es probarlas con casos. Otra: la salida cuesta 3 a 10 veces más que la entrada, y es el parámetro que más conviene vigilar. Y la tercera: el broker casi nunca se agota por ancho de banda (4 Mbit/s para 5000 mensajes por segundo) sino por conexiones y por mensajes copiados.

09 · Exploración interactiva

¿Alcanza este broker?, de extremo a extremo

Este laboratorio ejecuta el mismo modelo de capacidad del código anterior. Elegí la cantidad de dispositivos, cada cuánto publica cada uno, cuántos suscriptores recibe cada mensaje y el tipo de instalación. Las barras muestran qué fracción de la capacidad de mensajes y de la memoria usa la carga en cada una de las tres instalaciones: celeste si usa menos de la mitad, azul entre el 50 y el 100 % y rojo si se supera.

Capacidad de un broker MQTT

Mensajes que entran—
Mensajes que salen—
Ancho de banda (entrada / salida)—
Memoria para las conexiones—
Capacidad de la instalación—
Resultado—

Elegí los parámetros y presioná «Calcular».

Recorrido guiado

  1. Con los valores iniciales (10.000 dispositivos cada 60 s, 3 suscriptores, servidor virtual chico), calculá. 167 mensajes por segundo entran, 500 salen, 196 MB de memoria: «Con margen». En las tres instalaciones sobra capacidad.
  2. Pasá a cada 10 segundos con 10 suscriptores: la entrada es de 1000 mensajes por segundo y la salida llega a 10.000. El servidor chico queda «Al límite» y la Raspberry Pi, «No alcanza».
  3. Con la Raspberry Pi, 10.000 dispositivos cada 10 s y 3 suscriptores: 1000 entran y 3000 salen, la suma de 4000 supera la mitad pero entra en 5000: «Al límite». Con 10 suscriptores se pasa: «No alcanza».
  4. Elegí 100.000 dispositivos cada 60 s con la Raspberry Pi: 1954 MB de memoria contra 800: «No alcanza», por memoria y también por mensajes (6667 por segundo contra 5000). En el servidor chico, con margen: 1667 entran y 5000 salen.
  5. Volvé a 10.000 dispositivos cada 60 s y subí los suscriptores de 1 a 10: la entrada no cambia (167 por segundo) y la salida pasa de 167 a 1667. Agregar servicios que escuchan sale del broker, no del dispositivo.
  6. Probá cada 5 minutos con 100.000 dispositivos y 3 suscriptores: 333 mensajes por segundo de entrada y 1000 de salida, con la memoria de 1954 MB sin cambio. Espaciar las publicaciones baja el tráfico pero no la memoria de las conexiones.
Desafío: el costo de un suscriptor descuidado

Un servicio nuevo se suscribe a # «para ver qué pasa». En una flota de 10.000 dispositivos que publican cada 60 segundos, ese servicio recibe 167 mensajes por segundo, 14,4 millones por día. Con cargas de 40 bytes y 109 bytes por mensaje con encabezados, son 1,6 GB por día entrando a ese cliente, y el broker hace 167 copias más por segundo, aun cuando el servicio descarte casi todo. Si el servicio es lento y no consume a tiempo, el broker empieza a acumular mensajes en su cola (hasta el límite configurado) y gasta memoria; si el límite es alto, puede degradar a todos los demás. Una suscripción amplia es una carga sostenida para el broker; los filtros precisos y las listas de acceso son parte de la capacidad, no solo de la seguridad.

10 · Método de trabajo

Lista de verificación del broker

  1. Escribí el esquema de tópicos antes de instalar nada, con nombres en minúsculas, sin espacios ni tildes, estables y jerárquicos.
  2. Un tópico no cambia con cada mensaje: lo variable va en la carga.
  3. Probá los filtros con casos, incluidos los que contradicen la intuición (# y $SYS, el nivel padre, las mayúsculas).
  4. El dispositivo se suscribe a su propio tópico de comandos, dentro del código de conexión, y revisa el SUBACK.
  5. Sin acceso anónimo, con TLS, una credencial por dispositivo y listas de acceso con patrones por usuario.
  6. Evitá suscripciones traslapadas y filtros amplios en los servicios de producción.
  7. Calculá la carga: mensajes por segundo de entrada y salida, ancho de banda y memoria, con margen para picos y crecimiento.
  8. Fijá límites: conexiones, tamaño de mensaje, colas por cliente.
  9. Monitoreá el broker (los tópicos $SYS): conexiones, mensajes por segundo, memoria, mensajes descartados.
  10. Pensá en la caída del broker: qué hacen los dispositivos mientras no está y si hace falta un segundo broker o un puente.

Un hábito útil: suscribite a $SYS/# en un broker de prueba y mirá lo que publica. En poco tiempo se entiende cuántas conexiones hay, cuántos mensajes pasaron y cuánta memoria usa. Ver el pulso del sistema es la mejor manera de saber qué esperar de él.

11 · Comprensión

Confusiones frecuentes

«El broker valida el contenido de los mensajes»

No: solo mira el tópico y entrega los bytes de la carga sin interpretarlos. La validación de formato, rango y vigencia la hacen los extremos que publican y reciben.

«Un tópico con la hora me permite buscar las lecturas por fecha»

Un broker no es una base de datos: no guarda ni busca mensajes. Un tópico distinto por cada lectura solo acumula tópicos. La hora va en la carga, y la consulta histórica se hace en una base de datos.

«Suscribirme a # me da todo, incluido el estado del broker»

El comodín inicial no alcanza los tópicos que empiezan con $. Para ver las estadísticas del broker hay que suscribirse explícitamente a $SYS/#.

«Si me suscribí una vez, quedo suscripto para siempre»

Solo con una sesión persistente. Con una sesión limpia, las suscripciones se pierden al desconectar, y el cliente debe suscribirse otra vez en cada conexión. Revisar el SUBACK evita suponer una suscripción que el broker rechazó.

«Agregar un servicio que escucha no afecta a los dispositivos»

Al dispositivo, no: publica lo mismo. Pero el broker hace una copia más de cada mensaje, y con muchos suscriptores la salida se multiplica. Cada suscriptor nuevo cuesta capacidad del broker.

«El broker más potente soluciona cualquier diseño de tópicos»

Un esquema desordenado (tópicos explosivos, filtros amplios, comodines por todos lados) degrada hasta un broker enorme. El diseño de los tópicos y las suscripciones es parte de la capacidad.

12 · Práctica guiada

Predecí antes de comprobar

1. Coincidencias

Indicá si el filtro recibe el tópico: (a) casa/+ y casa/living; (b) casa/+ y casa/living/temperatura; (c) casa/# y casa; (d) # y $SYS/broker/clients; (e) casa/living y Casa/living.

Ver solución

(a) Sí. (b) No: el tópico tiene un nivel más. (c) Sí: # incluye el nivel padre. (d) No: los tópicos $ no se alcanzan con un comodín inicial. (e) No: distingue mayúsculas.

2. Carga de entrada y salida

Diez mil dispositivos publican cada 60 segundos y cada mensaje lo reciben 3 suscriptores. ¿Cuántos mensajes por segundo entran y cuántos salen?

Ver solución

Entran 10.000 / 60 ≈ 167 por segundo. Salen 167 × 3 = 500 por segundo. La salida es tres veces la entrada.

3. Memoria

Con 20 KB por conexión, ¿cuánta memoria necesita un broker con 10.000 dispositivos y 20 servicios conectados?

Ver solución

10.020 × 20 KB = 200.400 KB ≈ 196 MB. Para 100.000 dispositivos serían unos 1954 MB, casi 2 GB solo para las conexiones.

4. Lista de acceso

Escribí una regla con patrón que permita a cada dispositivo publicar solo en un tópico que contenga su nombre de usuario, por ejemplo casa/camara07/# para el usuario camara07.

Ver solución

pattern write casa/%u/# en el archivo de ACL de Mosquitto. El %u se reemplaza por el nombre del usuario conectado, y una sola línea cubre a toda la flota. Para los comandos: pattern read casa/%u/comandos.

5. Suscripciones traslapadas

Un cliente se suscribe a casa/# y a casa/+/temperatura. Se publica casa/living/temperatura. ¿Cuántas copias puede recibir y cómo se evita?

Ver solución

Hasta dos: el estándar permite una copia por cada suscripción que coincide. Se evita eliminando el traslape (con casa/# alcanza) o haciendo que el cliente descarte duplicados, por ejemplo por un identificador dentro de la carga.

6. Un tópico mejorable

Un firmware publica en /Casa/Cámara 07/Temperatura/2026-11-07T14:32. Enumerá los problemas y proponé uno mejor.

Ver solución

Problemas: barra inicial (primer nivel vacío), mayúsculas, espacio y tilde, y la hora en el tópico, que crea un tópico distinto por cada lectura. Mejor: casa/camara07/temperatura, con el momento de la medición dentro de la carga.

13 · Síntesis

Ideas para recordar

  • El broker autentica, autoriza, registra suscripciones, enruta y copia cada mensaje a cada suscriptor, guarda estado de sesión y publica estadísticas; no interpreta el contenido de las cargas.
  • Los nombres de tópico distinguen mayúsculas, usan / como separador y deben ser cortos, en minúsculas, sin espacios ni tildes ni barra inicial; un tópico es una dirección estable, no un dato.
  • Los filtros: + ocupa un nivel entero; # va solo y al final e incluye al nivel padre; los tópicos $ no se alcanzan con un comodín inicial.
  • El cliente revisa el SUBACK, se suscribe dentro de su código de conexión y evita las suscripciones traslapadas, que pueden duplicar mensajes.
  • Las suscripciones compartidas (MQTT 5) reparten los mensajes entre varias instancias de un servicio.
  • El broker puede estar en el borde, en la nube, en ambos con un puente, o en un clúster; la configuración mínima segura incluye TLS, usuarios, listas de acceso con patrones por usuario y límites.
  • La carga se calcula con aritmética simple: entrada = dispositivos ÷ intervalo; salida = entrada × suscriptores; ancho de banda; memoria por conexión.
  • La salida (el reparto) suele ser el límite, y agregar suscriptores multiplica la carga sin que el dispositivo cambie.
  • Los filtros precisos, los esquemas ordenados y la monitorización con $SYS son parte de la capacidad y de la seguridad del sistema.

¿Listo para el tema 27?

Antes de avanzar, escribí el esquema de tópicos de tu proyecto (telemetría, comandos, estado) y las suscripciones de cada actor (dispositivo, panel, servicio de archivo). Calculá los mensajes por segundo que entran y salen del broker con tu flota prevista, y escribí las líneas de la lista de acceso para un dispositivo y para el panel.

En el próximo tema pasamos al lado del firmware: publicar y suscribirse desde el dispositivo, con la conexión, los callbacks de los mensajes entrantes, la reconexión y el manejo de la sesión paso a paso.