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.
| Función | Qué hace | Decisión o riesgo |
|---|---|---|
| Aceptar conexiones | Mantiene un socket TCP abierto por cliente | Cuántas conexiones soporta; memoria por conexión |
| Autenticar | Verifica usuario y clave o certificado del cliente | Una credencial por dispositivo; sin acceso anónimo |
| Autorizar | Decide en qué tópicos puede publicar y suscribirse cada cliente | Listas de acceso por tópico; sin ellas, un equipo ve toda la flota |
| Registrar suscripciones | Guarda qué filtros pidió cada cliente | Memoria; suscripciones que se acumulan |
| Enrutar y reenviar | Compara cada publicación con los filtros y copia el mensaje a cada suscriptor | El reparto (fan-out) es el costo principal |
| Guardar mensajes | Retiene el último valor de un tópico y encola mensajes para clientes desconectados | Memoria y disco; límites de cola (tema 28) |
| Gestionar sesiones y garantías | Lleva cuenta de confirmaciones, reenvíos y calidad de servicio | Trabajo y estado por cliente (tema 28) |
| Publicar la última voluntad | Avisa que un cliente se cayó sin despedirse | Útil para detectar dispositivos mudos (tema 28) |
| Informar su estado | Publica 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.
| Aspecto | Lo que dice el estándar | Recomendación |
|---|---|---|
| Codificación y largo | Texto UTF-8, hasta 65.535 bytes, sin el carácter nulo y con al menos un carácter | Cortos: cada byte del tópico viaja en cada publicación |
| Mayúsculas | Distingue mayúsculas de minúsculas: Casa y casa son tópicos distintos | Todo en minúsculas |
| Separador | La barra / separa niveles; los niveles vacíos son válidos | No dejar niveles vacíos ni barra inicial: /casa tiene un primer nivel vacío |
| Comodines al publicar | Prohibidos: + y # no pueden estar en el nombre de un tópico publicado | — |
| Tópicos reservados | Los que empiezan con $ son del broker (por ejemplo, $SYS) | No usarlos para datos propios |
| Caracteres | Cualquier carácter UTF-8 es válido | Solo letras ASCII, números, guion y guion bajo: sin espacios, tildes ni símbolos |
| Tópico | Problema | Mejor |
|---|---|---|
/casa/Cámara 07/Temperatura | Barra inicial (primer nivel vacío), mayúsculas, espacio y tilde | casa/camara07/temperatura |
casa/camara07/temperatura/ | Barra final (último nivel vacío): es un tópico distinto del anterior | casa/camara07/temperatura |
datos | Un solo nivel para todo: no se puede filtrar por dispositivo ni por magnitud | casa/camara07/temperatura |
camara07 (el identificador y el dato mezclados) | Cada dato nuevo exige un tópico con otro formato | casa/camara07/estado/bateria |
casa/camara07/lectura/2026-11-07T14:32 | Un tópico distinto por cada lectura: explosión de tópicos | Un 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/#/xes inválido. Coincide con cualquier cantidad de niveles que sigan, incluido el nivel padre:casa/#recibecasa/living/temperaturapero tambiéncasaa 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//temperaturatiene 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 acasa/+/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
| Ubicación | Ventajas | Inconvenientes |
|---|---|---|
| En el borde (en el edificio o la planta) | Funciona sin Internet; latencia mínima; los datos sensibles no salen | Hay que operarlo; un solo sitio es un punto de falla |
| En la nube (propio o administrado) | Disponible desde cualquier lugar; escala; lo opera otro | Depende 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 corresponda | Más piezas; hay que decidir qué tópicos cruzan y en qué sentido |
| Un clúster de brokers | Alta disponibilidad y cientos de miles de conexiones | Complejidad 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
Elegí los parámetros y presioná «Calcular».
Recorrido guiado
- 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.
- 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».
- 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».
- 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.
- 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.
- 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
- Escribí el esquema de tópicos antes de instalar nada, con nombres en minúsculas, sin espacios ni tildes, estables y jerárquicos.
- Un tópico no cambia con cada mensaje: lo variable va en la carga.
- Probá los filtros con casos, incluidos los que contradicen la intuición (
#y$SYS, el nivel padre, las mayúsculas). - El dispositivo se suscribe a su propio tópico de comandos, dentro del código de conexión, y revisa el SUBACK.
- Sin acceso anónimo, con TLS, una credencial por dispositivo y listas de acceso con patrones por usuario.
- Evitá suscripciones traslapadas y filtros amplios en los servicios de producción.
- Calculá la carga: mensajes por segundo de entrada y salida, ancho de banda y memoria, con margen para picos y crecimiento.
- Fijá límites: conexiones, tamaño de mensaje, colas por cliente.
- Monitoreá el broker (los tópicos
$SYS): conexiones, mensajes por segundo, memoria, mensajes descartados. - 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
$SYSson 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.