Está en la página 1de 29

PARTE 1: Introducción a MQTT

“MQTT es un protocolo de transporte de mensajes de publicación / suscripción de Servidor de Cliente.


Es liviano, abierto, simple y está diseñado para ser fácil de implementar. Estas características lo hacen
ideal para su uso en muchas situaciones, incluidos entornos restringidos como la comunicación en
contextos de máquina a máquina (M2M) e Internet de las cosas (IoT) donde se requiere una pequeña
huella de código y / o el ancho de banda de la red es muy importante. "
Cita de la especificación oficial MQTT 3.1.1

El resumen de la especificación MQTT hace un buen trabajo al describir de qué se trata MQTT. Es un
protocolo binario y muy ligero, y debido a su mínima sobrecarga de paquetes, MQTT sobresale al
transferir datos a través del cable en comparación con protocolos como HTTP. Otro aspecto importante
del protocolo es que MQTT es extremadamente fácil de implementar en el lado del cliente. La facilidad
de uso fue una preocupación clave en el desarrollo de MQTT y lo hace perfecto para dispositivos
restringidos con recursos limitados en la actualidad.

Un poquito de historia

El protocolo MQTT fue inventado en 1999 por Andy Stanford-Clark (IBM) y Arlen Nipper (Arcom,
ahora Cirrus Link). Necesitaban un protocolo para una pérdida mínima de batería y un ancho de banda
mínimo para conectarse con oleoductos por satélite. Los dos inventores especificaron varios requisitos
para el protocolo futuro:

• Implementación simple
• Entrega de datos de calidad de servicio
• Ligero y ancho de banda eficiente
• Agnóstico de datos
• Conciencia continua de la sesión
Estos objetivos todavía están en el centro de MQTT. Sin embargo, el enfoque principal del protocolo ha
cambiado de sistemas integrados patentados para abrir casos de uso de Internet de las cosas (IoT). Este
cambio de enfoque ha creado mucha confusión sobre lo que significa el acrónimo MQTT. La respuesta
corta es que MQTT ya no se considera un acrónimo. MQTT es simplemente el nombre del protocolo.

La respuesta más larga es que el acrónimo anterior significaba MQ Telemetry Transport.

"MQ" se refiere a la serie MQ, un producto que IBM desarrolló para soportar el transporte de
telemetría MQ. Cuando Andy y Arlen crearon su protocolo en 1999, lo nombraron después del
producto de IBM. Muchas fuentes etiquetan MQTT incorrectamente como un protocolo de cola de
mensajes. Eso simplemente no es cierto. MQTT no es una solución de cola de mensajes tradicional
(aunque es posible poner mensajes en cola en ciertos casos, un hecho que discutiremos en detalle en
una próxima publicación). Durante los siguientes diez años, IBM usó el protocolo internamente hasta
que lanzaron MQTT 3.1 como una versión libre de regalías en 2010. Desde entonces, todos son
bienvenidos para implementar y usar el protocolo.

Nos familiarizamos con MQTT en 2012 y construimos la primera versión de HiveMQ ese mismo año.
En 2013, lanzamos HiveMQ al público. Junto con el lanzamiento de la especificación de protocolo,
IBM contribuyó con implementaciones de clientes MQTT al proyecto Paho recién fundado de la
Fundación Eclipse. Estos eventos fueron definitivamente una gran cosa para el protocolo porque hay
pocas posibilidades de una amplia adopción sin un ecosistema de apoyo.

OASIS Standard y versión actual

Aproximadamente 3 años después de la publicación inicial, se anunció que MQTT se estandarizaría


bajo las alas de OASIS, una organización abierta con el propósito de avanzar en los estándares. AMQP,
SAML y DocBook son solo algunos de los estándares OASIS publicados anteriormente. El proceso de
estandarización tomó alrededor de 1 año. El 29 de octubre de 2014, MQTT se convirtió en un estándar
OASIS aprobado oficialmente. MQTT 3.1.1 es la versión más nueva del protocolo. El cambio de
versión menor de 3.1 a 3.1.1 muestra que se hicieron pocos cambios a la versión anterior. Para obtener
información detallada sobre estos cambios, consulte nuestra publicación de blog sobre las ventajas de
3.1.1.

PARTE 2: Publish & Subscribe - MQTT Essentials

El patrón de publicación / suscripción (también conocido como pub / sub) proporciona una alternativa a
la arquitectura tradicional de cliente-servidor. En el modelo de servidor-cliente, un cliente se comunica
directamente con un punto final. El modelo pub / sub desacopla al cliente que envía un mensaje (el
editor) del cliente o clientes que reciben los mensajes (los suscriptores). Los editores y suscriptores
nunca se contactan directamente. De hecho, ni siquiera son conscientes de que el otro existe. La
conexión entre ellos es manejada por un tercer componente (el intermediario). El trabajo del agente es
filtrar todos los mensajes entrantes y distribuirlos correctamente a los suscriptores. Entonces,
profundicemos un poco más en algunos de los aspectos generales de pub / sub (hablaremos sobre los
detalles de MQTT en un minuto).
El aspecto más importante de pub / sub es el desacoplamiento del editor del mensaje del destinatario
(suscriptor). Este desacoplamiento tiene varias dimensiones:

• Desacoplamiento de espacio: el editor y el suscriptor no necesitan conocerse (por ejemplo, no


se intercambian la dirección IP ni el puerto).
• Desacoplamiento de tiempo: el editor y el suscriptor no necesitan ejecutarse al mismo tiempo.
• Desacoplamiento de sincronización: las operaciones en ambos componentes no necesitan ser
interrumpidas durante la publicación o recepción.

En resumen, el modelo pub / sub elimina la comunicación directa entre el editor del mensaje y el
destinatario / suscriptor. La actividad de filtrado del agente hace posible controlar qué cliente /
suscriptor recibe qué mensaje. El desacoplamiento tiene tres dimensiones: espacio, tiempo y
sincronización.

Escalabilidad

Pub / Sub escala mejor que el enfoque tradicional de cliente-servidor. Esto se debe a que las
operaciones en el intermediario pueden estar altamente paralelizadas y los mensajes pueden procesarse
de una manera controlada por eventos. El almacenamiento en caché de mensajes y el enrutamiento
inteligente de mensajes a menudo son factores decisivos para mejorar la escalabilidad. Sin embargo,
ampliar a millones de conexiones es un desafío. Se puede lograr un nivel tan alto de conexiones con
nodos de intermediario agrupados para distribuir la carga en más servidores individuales utilizando
equilibradores de carga. (este tema está más allá del alcance del artículo actual, lo cubriremos en una
publicación separada).

Filtrado de mensajes

Está claro que el corredor desempeña un papel fundamental en el proceso de pub / sub. Pero, ¿cómo
logra el agente filtrar todos los mensajes para que cada suscriptor reciba solo mensajes de interés?
Como verá, el corredor tiene varias opciones de filtrado:

OPCIÓN 1: FILTRADO BASADO EN SUJETOS


Este filtrado se basa en el tema o tema que forma parte de cada mensaje. El cliente receptor se suscribe
al corredor para temas de interés. A partir de ese momento, el intermediario se asegura de que el cliente
receptor reciba todos los mensajes publicados en los temas suscritos. En general, los temas son cadenas
con una estructura jerárquica que permiten el filtrado en función de un número limitado de expresiones.

OPCIÓN 2: FILTRADO BASADO EN CONTENIDO


En el filtrado basado en contenido, el intermediario filtra el mensaje en función de un lenguaje de filtro
de contenido específico. Los clientes receptores se suscriben para filtrar las consultas de los mensajes
que les interesan. Una desventaja significativa de este método es que el contenido del mensaje debe
conocerse de antemano y no puede cifrarse ni cambiarse fácilmente.

OPCIÓN 3: FILTRADO BASADO EN TIPO


Cuando se utilizan lenguajes orientados a objetos, el filtrado basado en el tipo / clase de un mensaje
(evento) es una práctica común. Por ejemplo, un suscriptor puede escuchar todos los mensajes, que son
de tipo Excepción o cualquier subtipo.
Por supuesto, publicar / suscribirse no es la respuesta para cada caso de uso. Hay algunas cosas que
debe considerar antes de usar este modelo. El desacoplamiento de editor y suscriptor, que es la clave en
pub / sub, presenta algunos desafíos propios. Por ejemplo, debe saber de antemano cómo se estructuran
los datos publicados. Para el filtrado basado en temas, tanto el editor como el suscriptor necesitan saber
qué temas usar. Otra cosa a tener en cuenta es la entrega de mensajes. El editor no puede asumir que
alguien está escuchando los mensajes que se envían. En algunos casos, es posible que ningún suscriptor
lea un mensaje en particular.

MQTT

Ahora que hemos explorado el modelo de publicación / suscripción en general, centrémonos


específicamente en MQTT. Dependiendo de lo que quieras lograr, MQTT incorpora todos los aspectos
de pub / sub que hemos mencionado:

• MQTT desacopla espacialmente al editor y al suscriptor. Para publicar o recibir mensajes, los
editores y suscriptores solo necesitan conocer el nombre de host / IP y el puerto del corredor

• MQTT se desacopla por tiempo. Aunque la mayoría de los casos de uso de MQTT entregan
mensajes en tiempo casi real, si lo desea, el agente puede almacenar mensajes para clientes que
no están en línea. (Se deben cumplir dos condiciones para almacenar mensajes: el cliente se
conectó con una sesión persistente y se suscribió a un tema con una Calidad de servicio superior
a 0).

• MQTT funciona de forma asíncrona. Debido a que la mayoría de las bibliotecas de clientes
funcionan de manera asíncrona y se basan en devoluciones de llamada o un modelo similar, las
tareas no se bloquean mientras esperan un mensaje o publican un mensaje. En ciertos casos de
uso, la sincronización es deseable y posible. Para esperar un mensaje determinado, algunas
bibliotecas tienen API síncronas. Pero el flujo suele ser asíncrono.

Otra cosa que debe mencionarse es que MQTT es especialmente fácil de usar en el lado del cliente. La
mayoría de los sistemas pub / sub tienen la lógica en el lado del corredor, pero MQTT es realmente la
esencia de pub / sub cuando se usa una biblioteca cliente y eso lo convierte en un protocolo ligero para
dispositivos pequeños y restringidos.

MQTT utiliza el filtrado de mensajes basado en temas. Cada mensaje contiene un tema (asunto) que el
agente puede usar para determinar si un cliente suscriptor recibe el mensaje o no. Consulte la parte 5 de
MQTT Essentials para obtener más información sobre el concepto de temas. Si lo desea, también puede
configurar el filtrado basado en contenido con el agente HiveMQ MQTT y nuestro sistema de
complementos personalizado.

Para manejar los desafíos de un sistema pub / subs, MQTT tiene tres niveles de calidad de servicio
(QoS). Puede especificar fácilmente que un mensaje se entregue correctamente del cliente al
intermediario o del intermediario a un cliente. Sin embargo, existe la posibilidad de que nadie se
suscriba al tema en particular. Si esto es un problema, el corredor debe saber cómo manejar la
situación. Por ejemplo, el agente HiveMQ MQTT tiene un sistema de complementos que puede
resolver estos casos. Puede hacer que el corredor tome medidas o simplemente registrar cada mensaje
en una base de datos para análisis históricos. Para mantener flexible el árbol jerárquico de temas, es
importante diseñar el árbol de temas con mucho cuidado y dejar espacio para futuros casos de uso. Si
sigue estas estrategias, MQTT es perfecto para configuraciones de producción.

Distinción de las colas de mensajes

Hay mucha confusión sobre el nombre MQTT y si el protocolo se implementa como una cola de
mensajes o no. Intentaremos arrojar algo de luz sobre el tema y explicar las diferencias. En nuestra
última publicación, mencionamos que MQTT se refiere al producto MQseries de IBM y no tiene nada
que ver con la "cola de mensajes". Independientemente del origen del nombre, es útil comprender las
diferencias entre MQTT y una cola de mensajes tradicional:

Una cola de mensajes almacena el mensaje hasta que se consumen. Cuando usa una cola de
mensajes, cada mensaje entrante se almacena en la cola hasta que un cliente lo recoge (a menudo
llamado consumidor). Si ningún cliente recoge el mensaje, el mensaje permanece atascado en la cola y
espera a ser consumido. En una cola de mensajes, no es posible que ningún cliente procese un mensaje,
ya que está en MQTT si nadie se suscribe a un tema.

Un cliente solo consume un mensaje. Otra gran diferencia es que, en una cola de mensajes
tradicional, solo un consumidor puede procesar un mensaje. La carga se distribuye entre todos los
consumidores para una cola. En MQTT, el comportamiento es todo lo contrario: cada suscriptor que se
suscribe al tema recibe el mensaje.

Las colas se nombran y deben crearse explícitamente. Una cola es mucho más rígida que un tema.
Antes de que se pueda usar una cola, la cola se debe crear explícitamente con un comando separado.
Solo después de nombrar y crear la cola es posible publicar o consumir mensajes. Por el contrario, los
temas MQTT son extremadamente flexibles y se pueden crear sobre la marcha.

PART 3 Client, Broker / Server and Connection Establishment


Debido a que MQTT desacopla al editor del suscriptor, las conexiones del cliente siempre son
manejadas por un intermediario. Antes de entrar en detalles sobre estas conexiones, seamos claros
acerca de lo que entendemos por cliente y corredor.

Cliente
Cuando hablamos de un cliente, casi siempre nos referimos a un cliente MQTT. Tanto los editores
como los suscriptores son clientes MQTT. Las etiquetas de editor y suscriptor se refieren a si el cliente
está actualmente publicando mensajes o suscribiéndose a mensajes (la funcionalidad de publicación y
suscripción también se puede implementar en el mismo cliente MQTT). Un cliente MQTT es cualquier
dispositivo (desde un microcontrolador hasta un servidor completo) que ejecuta una biblioteca MQTT
y se conecta a un agente MQTT a través de una red. Por ejemplo, el cliente MQTT puede ser un
dispositivo muy pequeño y con recursos limitados que se conecta a través de una red inalámbrica y
tiene una biblioteca mínima. El cliente MQTT también puede ser una computadora típica que ejecuta
un cliente gráfico MQTT con fines de prueba. Básicamente, cualquier dispositivo que hable MQTT a
través de una pila TCP / IP puede llamarse cliente MQTT. La implementación del cliente del protocolo
MQTT es muy sencilla y simplificada. La facilidad de implementación es una de las razones por las
que MQTT es ideal para dispositivos pequeños. Las bibliotecas de cliente MQTT están disponibles
para una gran variedad de lenguajes de programación. Por ejemplo, Android, Arduino, C, C ++, C #,
Go, iOS, Java, JavaScript y .NET. Puede ver una lista completa en el wiki de MQTT.
Corredor
La contraparte del cliente MQTT es el intermediario MQTT. El corredor está en el corazón de cualquier
protocolo de publicación / suscripción. Dependiendo de la implementación, un intermediario puede
manejar hasta miles de clientes MQTT conectados simultáneamente. El corredor es responsable de
recibir todos los mensajes, filtrar los mensajes, determinar quién está suscrito a cada mensaje y enviar
el mensaje a estos clientes suscritos. El intermediario también contiene los datos de sesión de todos los
clientes que tienen sesiones persistentes, incluidas las suscripciones y los mensajes perdidos (más
detalles). Otra responsabilidad del corredor es la autenticación y autorización de los clientes. Por lo
general, el intermediario es extensible, lo que facilita la autenticación, la autorización y la integración
personalizadas en los sistemas de fondo. La integración es particularmente importante porque el
intermediario es con frecuencia el componente que está expuesto directamente en Internet, maneja
muchos clientes y necesita pasar mensajes a los sistemas de análisis y procesamiento posteriores. Como
se discutió en una publicación anterior, suscribirse a todos los mensajes no es realmente una opción. En
resumen, el intermediario es el centro central a través del cual debe pasar cada mensaje. Por lo tanto, es
importante que su corredor sea altamente escalable, integrable en sistemas de back-end, fácil de
monitorear y (por supuesto) resistente a fallas. HiveMQ cumple con estos requisitos mediante el uso de
procesamiento de red de última generación basado en eventos, un sistema de complemento abierto y
proveedores de monitoreo estándar.

MQTT Connection

El protocolo MQTT se basa en TCP / IP. Tanto el cliente como el intermediario deben tener una pila
TCP / IP.

La conexión MQTT es siempre entre un cliente y el intermediario. Los clientes nunca se conectan entre
sí directamente. Para iniciar una conexión, el cliente envía un mensaje CONEXIÓN al intermediario.
El agente responde con un mensaje CONNACK y un código de estado. Una vez que se establece la
conexión, el intermediario la mantiene abierta hasta que el cliente envía un comando de desconexión o
la conexión se interrumpe.
Conexión MQTT a través de un NAT
En muchos casos de uso común, el cliente MQTT está ubicado detrás de un enrutador que utiliza la
traducción de direcciones de red (NAT) para traducir desde una dirección de red privada (como
192.168.x.x, 10.0.x.x) a una dirección pública. Como ya mencionamos, el cliente MQTT inicia la
conexión enviando un mensaje CONNECT al intermediario. Debido a que el agente tiene una dirección
pública y mantiene la conexión abierta para permitir el envío y la recepción bidireccionales de
mensajes (después de la CONEXIÓN inicial), no hay ningún problema con los clientes que se
encuentran detrás de un NAT.

El cliente inicia la conexión con el mensaje CONNECT ###


Ahora veamos el mensaje del comando MQTT CONNECT. Para iniciar una conexión, el cliente envía
un mensaje de comando al intermediario. Si este mensaje CONECTAR está mal formado (de acuerdo
con la especificación MQTT) o pasa demasiado tiempo entre la apertura de un socket de red y el envío
del mensaje de conexión, el intermediario cierra la conexión. Este comportamiento disuade a los
clientes maliciosos que pueden ralentizar al agente. Un cliente de buen carácter envía un mensaje de
conexión con el siguiente contenido (entre otras cosas):

Alguna información incluida en un mensaje CONNECT es probablemente más interesante para los
implementadores de una biblioteca MQTT que para los usuarios de esa biblioteca. Para todos los
detalles, eche un vistazo a la especificación MQTT 3.1.1.

Nos centraremos en las siguientes opciones:

Identificación del cliente

El identificador de cliente (ClientId) identifica a cada cliente MQTT que se conecta a un intermediario
MQTT. El agente utiliza el ClientID para identificar al cliente y el estado actual del cliente. Por lo
tanto, este ID debe ser único por cliente y agente. En MQTT 3.1.1 (el estándar actual), puede enviar un
ClientId vacío, si no necesita un estado retenido por el corredor. El ClientID vacío da como resultado
una conexión sin ningún estado. En este caso, el indicador de sesión limpia debe establecerse en
verdadero o el intermediario rechazará la conexión.

Sesión limpia

El indicador de sesión limpia le dice al agente si el cliente desea establecer una sesión persistente o no.
En una sesión persistente (CleanSession = false), el intermediario almacena todas las suscripciones para
el cliente y todos los mensajes perdidos para el cliente que se suscribió con un Nivel de calidad de
servicio (QoS) 1 o 2. Si la sesión no es persistente (CleanSession = true ), el intermediario no almacena
nada para el cliente y purga toda la información de cualquier sesión persistente anterior.

Usuario Contraseña

MQTT puede enviar un nombre de usuario y una contraseña para la autenticación y autorización del
cliente. Sin embargo, si esta información no está encriptada o cifrada (ya sea por implementación o
TLS), la contraseña se envía en texto sin formato. Recomendamos encarecidamente el uso de nombres
de usuario y contraseñas junto con un transporte seguro. Los corredores como HiveMQ pueden
autenticar clientes con un certificado SSL, por lo que no se necesita nombre de usuario ni contraseña.

Mensaje de voluntad

El último mensaje de voluntad es parte de la función Última voluntad y testamento (LWT) de MQTT.
Este mensaje notifica a otros clientes cuando un cliente se desconecta sin gracia. Cuando un cliente se
conecta, puede proporcionar al intermediario una última voluntad en forma de un mensaje MQTT y un
tema dentro del mensaje CONEXIÓN. Si el cliente se desconecta sin gracia, el intermediario envía el
mensaje LWT en nombre del cliente. Puede obtener más información sobre LWT en la parte 9 de esta
serie.

Mantener viva

Mantener vivo es un intervalo de tiempo en segundos que el cliente especifica y comunica al


intermediario cuando se establece la conexión. Este intervalo define el período de tiempo más largo que
el corredor y el cliente pueden soportar sin enviar un mensaje. El cliente se compromete a enviar
mensajes regulares de solicitud PING al corredor. El corredor responde con una respuesta PING. Este
método permite a ambos lados determinar si el otro todavía está disponible. Consulte la parte 10 de esta
serie para obtener información detallada sobre la funcionalidad MQTT Keep Live.

Básicamente, esa es toda la información que es todo lo que necesita para conectarse a un agente MQTT
desde un cliente MQTT. Las bibliotecas individuales a menudo tienen opciones adicionales que puede
configurar. Por ejemplo, la forma en que los mensajes en cola se almacenan en una implementación
específica.

Respuesta del agente con un mensaje CONNACK

Cuando un corredor recibe un mensaje CONEXIÓN, está obligado a responder con un mensaje
CONEXIÓN.

El mensaje CONNACK contiene dos entradas de datos:

• La sesión presente bandera


• Una bandera de reconocimiento de conexión

Indicador de sesión actual

El indicador de sesión actual le dice al cliente si el intermediario ya tiene una sesión persistente
disponible de interacciones anteriores con el cliente. Cuando un cliente se conecta con Clean Session
establecido en true, el indicador de sesión presente siempre es falso porque no hay sesión disponible. Si
un cliente se conecta con la sesión limpia establecida en falso, hay dos posibilidades: si la información
de la sesión está disponible para el ID del cliente. y el intermediario ha almacenado información de la
sesión, el indicador de sesión actual es verdadero. De lo contrario, si el intermediario no tiene ninguna
información de sesión para el ID de cliente, el indicador de sesión actual es falso. Este indicador se
agregó en MQTT 3.1.1 para ayudar a los clientes a determinar si necesitan suscribirse a temas o si los
temas aún están almacenados en una sesión persistente.

Bandera de reconocimiento de conexión

El segundo indicador en el mensaje CONNACK es el indicador de confirmación de conexión. Este


indicador contiene un código de retorno que le dice al cliente si el intento de conexión fue exitoso.

Aquí están los códigos de retorno de un vistazo:

Return
Return Code Response
Code

0 Connection accepted

Connection refused, unacceptable protocol


1
version

2 Connection refused, identifier rejected

3 Connection refused, server unavailable

Connection refused, bad user name or


4
password

5 Connection refused, not authorized

Para obtener una explicación más detallada de cada uno de estos códigos, consulte la especificación
MQTT.
PARTE 4: MQTT Publish, Subscribe & Unsubscribe
Publish
Un cliente MQTT puede publicar mensajes tan pronto como se conecta a un intermediario. MQTT
utiliza el filtrado basado en temas de los mensajes en el intermediario (consulte la parte 2 para más
detalles). Cada mensaje debe contener un tema que el intermediario pueda usar para reenviar el
mensaje a los clientes interesados. Típicamente, cada mensaje tiene una carga útil que contiene los
datos a transmitir en formato byte. MQTT es independiente de los datos. El caso de uso del cliente
determina cómo se estructura la carga útil. El cliente emisor (editor) decide si desea enviar datos
binarios, datos de texto o incluso XML o JSON completos. Un mensaje PUBLICAR en MQTT tiene
varios atributos que queremos analizar en detalle:

Topic Name: El nombre del tema es una cadena simple que está estructurada jerárquicamente con
barras diagonales como delimitadores. Por ejemplo, "mihome / livingroom / temperature" o "Germany /
Munich / Octoberfest / people". Para obtener detalles sobre los temas, consulte la parte 5 de MQTT
Essentials.

QoS Este número indica el nivel de calidad de servicio (QoS) del mensaje. Hay tres niveles: 0,1 y 2. El
nivel de servicio determina qué tipo de garantía tiene un mensaje para llegar al destinatario (cliente o
corredor). Para obtener detalles sobre QoS, consulte la parte 6 de MQTT Essentials.

Retain Flag Este indicador define si el intermediario guarda el mensaje como el último valor válido
conocido para un tema específico. Cuando un nuevo cliente se suscribe a un tema, recibe el último
mensaje retenido sobre ese tema. Para obtener detalles sobre los mensajes retenidos, consulte la parte 8
de MQTT Essentials.

Payload: Carga útil Este es el contenido real del mensaje. MQTT es independiente de los datos. Es
posible enviar imágenes, texto en cualquier codificación, datos cifrados y prácticamente todos los datos
en binario.

Packet Identifier El identificador de paquete identifica de forma exclusiva un mensaje a medida que
fluye entre el cliente y el intermediario. El identificador de paquete solo es relevante para niveles de
QoS mayores que cero. La biblioteca del cliente y / o el intermediario son responsables de configurar
este identificador MQTT interno.

DUP flag El indicador indica que el mensaje es un duplicado y se reenvió porque el destinatario
(cliente o corredor) no reconoció el mensaje original. Esto solo es relevante para QoS mayor que 0. Por
lo general, el mecanismo de reenvío / duplicación es manejado por la biblioteca del cliente MQTT o el
intermediario como un detalle de implementación. Para obtener más información, parte 6 de MQTT
Essentials.

Cuando un cliente envía un mensaje a un intermediario MQTT para su publicación, el intermediario lee
el mensaje, lo reconoce (de acuerdo con el nivel de QoS) y procesa el mensaje. El procesamiento por
parte del corredor incluye determinar qué clientes se han suscrito al tema y enviarles el mensaje.

El cliente que inicialmente publica el mensaje solo está preocupado por entregar el mensaje
PUBLICAR al intermediario. Una vez que el agente recibe el mensaje PUBLICAR, es responsabilidad
del agente entregar el mensaje a todos los suscriptores. El cliente de publicación no recibe ningún
comentario acerca de si alguien está interesado en el mensaje publicado o cuántos clientes recibieron el
mensaje del agente.

Suscribir

Publicar un mensaje no tiene sentido si nadie lo recibe. En otras palabras, si no hay clientes para
suscribirse a los temas de los mensajes. Para recibir mensajes sobre temas de interés, el cliente envía un
mensaje SUSCRIBIRSE al agente MQTT. Este mensaje de suscripción es muy simple, contiene un
identificador de paquete único y una lista de suscripciones.

Atributos de suscripción MQTT

Packet Identifier El identificador de paquete identifica de forma exclusiva un mensaje a medida que
fluye entre el cliente y el intermediario. La biblioteca del cliente y / o el intermediario son responsables
de configurar este identificador MQTT interno.

List of Subscriptions Un mensaje SUSCRIBIR puede contener múltiples suscripciones para un


cliente. Cada suscripción se compone de un tema y un nivel de QoS. El tema en el mensaje de
suscripción puede contener comodines que permitan suscribirse a un patrón de tema en lugar de a un
tema específico. Si hay suscripciones superpuestas para un cliente, el intermediario entrega el mensaje
que tiene el nivel más alto de QoS para ese tema.

Suback

Para confirmar cada suscripción, el agente envía un mensaje de confirmación SUBACK al cliente. Este
mensaje contiene el identificador de paquete del mensaje de suscripción original (para identificar
claramente el mensaje) y una lista de códigos de retorno.
Packet Identifier El identificador de paquete es un identificador único utilizado para identificar un
mensaje. Es lo mismo que en el mensaje SUSCRIBIRSE.

Return Code El intermediario envía un código de retorno para cada tema / par de QoS que recibe en el
mensaje SUSCRIBIRSE. Por ejemplo, si el mensaje SUSCRIBIRSE tiene cinco suscripciones, el
mensaje SUBACK contiene cinco códigos de retorno. El código de retorno reconoce cada tema y
muestra el nivel de QoS que otorga el intermediario. Si el agente rechaza una suscripción, el mensaje
SUBACK contiene un código de retorno de falla para ese tema específico. Por ejemplo, si el cliente no
tiene permisos suficientes para suscribirse al tema o el tema está mal formado.

Return Return Code


Code Response

Success - Maximum
0
QoS 0

Success - Maximum
1
QoS 1

Success - Maximum
2
QoS 2

128 Failure
Después de que un cliente envía con éxito el mensaje SUBSCRIBE y recibe el mensaje SUBACK,
obtiene todos los mensajes publicados que coinciden con un tema en las suscripciones que contenía el
mensaje SUBSCRIBE.

Unsubscribe
La contraparte del mensaje SUBSCRIBE es el mensaje UNSUBSCRIBE. Este mensaje elimina las
suscripciones existentes de un cliente en el intermediario. El mensaje UNSUBSCRIBE es similar al
mensaje SUBSCRIBE y tiene un identificador de paquete y una lista de temas.

Packet Identifier El identificador de paquete identifica de forma exclusiva un mensaje a medida que
fluye entre el cliente y el intermediario. La biblioteca del cliente y / o el intermediario son responsables
de configurar este identificador MQTT interno.
List of Topic La lista de temas puede contener múltiples temas de los cuales el cliente desea darse de
baja. Solo es necesario enviar el tema (sin QoS). El intermediario cancela la suscripción del tema,
independientemente del nivel de QoS con el que se suscribió originalmente.

Unsuback
Para confirmar la cancelación de la suscripción, el intermediario envía un mensaje de confirmación de
DESENVERSA al cliente. Este mensaje contiene solo el identificador de paquete del mensaje
UNSUBSCRIBE original (para identificar claramente el mensaje).

Packet Identifier El identificador de paquete identifica de forma exclusiva el mensaje. Como ya se


mencionó, este es el mismo identificador de paquete que está en el mensaje UNSUBSCRIBE.
Después de recibir UNSUBACK del intermediario, el cliente puede asumir que las suscripciones en el
mensaje UNSUBSCRIBE se eliminan.

PARTE 5: MQTT Topics & Best Practices


Topics
En MQTT, el tema de la palabra se refiere a una cadena UTF-8 que el intermediario utiliza para filtrar
mensajes para cada cliente conectado. El tema consta de uno o más niveles de tema. Cada nivel de tema
está separado por una barra diagonal (separador de nivel de tema).

En comparación con una cola de mensajes, los temas MQTT son muy ligeros. El cliente no necesita
crear el tema deseado antes de publicarlo o suscribirse a él. El corredor acepta cada tema válido sin
ninguna inicialización previa.
Aquí hay algunos ejemplos de temas:
myhome/groundfloor/livingroom/temperature
USA/California/San Francisco/Silicon Valley
5ff4a2ce-e485-40f4-826c-b1a5d81be9b6/status
Germany/Bavaria/car/2382340923453/latitude
Tenga en cuenta que cada tema debe contener al menos 1 carácter y que la cadena del tema permite
espacios vacíos. Los temas distinguen entre mayúsculas y minúsculas. Por ejemplo, _myhome /
temperature y _MyHome / Temperature son dos temas diferentes. Además, la barra diagonal sola es un
tema válido.
Wildcards
Cuando un cliente se suscribe a un tema, puede suscribirse al tema exacto de un mensaje publicado o
puede usar comodines para suscribirse a múltiples temas simultáneamente. Un comodín solo se puede
usar para suscribirse a temas, no para publicar un mensaje. Hay dos tipos diferentes de comodines:
_single-level y _multi-level.

Single Level: +
Como su nombre indica, un comodín de un solo nivel reemplaza un nivel de tema. El símbolo más
representa un comodín de un solo nivel en un tema.

Cualquier tema coincide con un tema con comodín de nivel único si contiene una cadena arbitraria en
lugar del comodín. Por ejemplo, una suscripción a _myhome / groundfloor / + / temperature puede
producir los siguientes resultados:

Multi Level: #
El comodín multinivel cubre muchos niveles de temas. El símbolo hash representa el comodín
multinivel en el tema. Para que el intermediario determine qué temas coinciden, el comodín multinivel
debe colocarse como el último personaje del tema y debe ir precedido de una barra diagonal.
Cuando un cliente se suscribe a un tema con un comodín multinivel, recibe todos los mensajes de un
tema que comienza con el patrón antes del carácter comodín, sin importar qué tan largo o profundo sea
el tema. Si especifica solo el comodín multinivel como tema (_ #), recibirá todos los mensajes que se
envían al agente MQTT. Si espera un alto rendimiento, la suscripción solo con un comodín multinivel
es un antipatrón (consulte las mejores prácticas a continuación).

Temas que comienzan con $


En general, puede nombrar sus temas MQTT como lo desee. Sin embargo, hay una excepción: los
temas que comienzan con un símbolo $ tienen un propósito diferente. Estos temas no forman parte de
la suscripción cuando se suscribe al comodín multinivel como tema (#). Los temas $ -symbol están
reservados para las estadísticas internas del agente MQTT. Los clientes no pueden publicar mensajes en
estos temas. Por el momento, no existe una estandarización oficial para tales temas. Comúnmente, $
SYS / se usa para toda la siguiente información, pero las implementaciones de los corredores varían.
Una sugerencia para $ SYS-topics está en el wiki de MQTT GitHub. Aquí hay unos ejemplos:
$SYS/broker/clients/connected
$SYS/broker/clients/disconnected
$SYS/broker/clients/total
$SYS/broker/messages/sent
$SYS/broker/uptime

Resumen
Estos son los conceptos básicos de los temas de mensajes MQTT. Como puede ver, los temas MQTT
son dinámicos y brindan una gran flexibilidad. Cuando usa comodines en aplicaciones del mundo real,
hay algunos desafíos que debe tener en cuenta. Hemos recopilado las mejores prácticas que hemos
aprendido al trabajar extensamente con MQTT en varios proyectos y siempre estamos abiertos a
sugerencias o discusiones sobre estas prácticas. Use los comentarios para comenzar una conversación.
¡Háganos saber sus mejores prácticas o si no está de acuerdo con una de las nuestras!
Mejores prácticas
Nunca use una barra inclinada hacia adelante
Se permite una barra diagonal delantera en MQTT. Por ejemplo, / myhome / planta baja / sala de estar.
Sin embargo, la barra inclinada hacia adelante introduce un nivel de tema innecesario con un carácter
cero en el frente. El cero no proporciona ningún beneficio y a menudo conduce a la confusión.
Nunca use espacios en un tema
Un espacio es el enemigo natural de cada programador. Cuando las cosas no van como deberían, los
espacios hacen que sea mucho más difícil de leer y depurar temas. Al igual que con las barras
inclinadas hacia adelante, el hecho de que algo esté permitido no significa que deba usarse. UTF-8
tiene muchos tipos diferentes de espacios en blanco, por lo que se deben evitar estos caracteres poco
comunes.
Mantenga el tema breve y conciso.
Cada tema se incluye en cada mensaje en el que se utiliza. Haga que sus temas sean lo más breves y
concisos posible. Cuando se trata de dispositivos pequeños, cada byte cuenta y la longitud del tema
tiene un gran impacto.
Utilice solo caracteres ASCII, evite caracteres no imprimibles
Debido a que los caracteres no ASCII UTF-8 a menudo se muestran incorrectamente, es muy difícil
encontrar errores tipográficos o problemas relacionados con el conjunto de caracteres. A menos que sea
absolutamente necesario, recomendamos evitar el uso de caracteres no ASCII en un tema.
Incruste un identificador único o el ID del cliente en el tema
Puede ser muy útil incluir el identificador único del cliente de publicación en el tema. El identificador
único en el tema le ayuda a identificar quién envió el mensaje. La ID incrustada se puede usar para
hacer cumplir la autorización. Solo un cliente que tenga la misma ID de cliente que la ID del tema
puede publicar en ese tema. Por ejemplo, un cliente con la identificación _client1 puede publicar en
_client1 / status, pero no puede publicar en _client2 / status.
No se suscriba a #
A veces, es necesario suscribirse a todos los mensajes que se transfieren a través del intermediario. Por
ejemplo, para persistir todos los mensajes en una base de datos. No se suscriba a todos los mensajes en
un intermediario utilizando un cliente MQTT y suscribiéndose a un comodín multinivel. Con
frecuencia, el cliente suscriptor no puede procesar la carga de mensajes que resulta de este método
(especialmente si tiene un rendimiento masivo). Nuestra recomendación es implementar una extensión
en el broker MQTT. Por ejemplo, con el sistema de complementos de HiveMQ puede engancharse al
comportamiento de HiveMQ y agregar una rutina asincrónica para procesar cada mensaje entrante y
persistirlo en una base de datos.
No olvides la extensibilidad
Los temas son un concepto flexible y no hay necesidad de asignarlos previamente de ninguna manera.
Sin embargo, tanto el editor como el suscriptor deben conocer el tema. Es importante pensar en cómo
se pueden ampliar los temas para permitir nuevas características o productos. Por ejemplo, si su
solución de hogar inteligente agrega nuevos sensores, debería ser posible agregarlos a su árbol de temas
sin cambiar toda la jerarquía de temas.
Utilice temas específicos, no generales.
Cuando nombre los temas, no los use de la misma manera que en una cola. Diferencie sus temas tanto
como sea posible. Por ejemplo, si tiene tres sensores en su sala de estar, cree temas para _home / sala
de estar / temperatura, _home / sala de estar / brillo y _home / sala de estar / humedad. No envíe todos
los valores sobre _myhome / livingroom. El uso de un solo tema para todos los mensajes es un anti
patrón. La nomenclatura específica también le permite utilizar otras funciones MQTT, como mensajes
retenidos. Para obtener más información sobre los mensajes retenidos, consulte la parte 8 de la serie
Essentials.
PARTE 6 Quality of Service
El nivel de calidad de servicio (QoS) es un acuerdo entre el remitente de un mensaje y el receptor de un
mensaje que define la garantía de entrega de un mensaje específico. Hay 3 niveles de QoS en MQTT:

• A lo más una vez (0)


• Al menos una vez (1)
• Exactamente una vez (2).

Cuando habla de QoS en MQTT, debe considerar los dos lados de la entrega del mensaje:

1. Entrega de mensajes del cliente de publicación al intermediario.


2. Entrega de mensajes del intermediario al cliente suscriptor.

Analizaremos los dos lados de la entrega del mensaje por separado porque hay diferencias sutiles entre
los dos. El cliente que publica el mensaje al intermediario define el nivel de QoS del mensaje cuando lo
envía al intermediario. El intermediario transmite este mensaje a los clientes suscriptores utilizando el
nivel de QoS que cada cliente suscriptor define durante el proceso de suscripción. Si el cliente
suscriptor define una QoS más baja que el cliente de publicación, el intermediario transmite el mensaje
con la menor calidad de servicio.

¿Por qué es importante la calidad del servicio?


QoS es una característica clave del protocolo MQTT. QoS le da al cliente el poder de elegir un nivel de
servicio que coincida con la confiabilidad de su red y la lógica de la aplicación. Debido a que MQTT
gestiona la retransmisión de mensajes y garantiza la entrega (incluso cuando el transporte subyacente
no es confiable), QoS facilita mucho la comunicación en redes poco confiables.

¿Como funciona?
Echemos un vistazo más de cerca a cómo se implementa cada nivel de QoS en el protocolo MQTT y
cómo funciona:

QoS 0 – como máximo una vez

El nivel mínimo de QoS es cero. Este nivel de servicio garantiza una entrega de mejor esfuerzo. No hay
garantía de entrega. El destinatario no acusa recibo del mensaje y el remitente no almacena ni reenvía
el mensaje. El nivel de calidad de servicio 0 a menudo se denomina "disparar y olvidar" y proporciona
la misma garantía que el protocolo TCP subyacente.
QoS 1 - al menos una vez

El nivel de calidad de servicio 1 garantiza que un mensaje se entregue al menos una vez al receptor. El
remitente almacena el mensaje hasta que recibe un paquete PUBACK del receptor que acusa recibo del
mensaje. Es posible que se envíe o entregue un mensaje varias veces.

El remitente usa el identificador de paquete en cada paquete para hacer coincidir el paquete PUBLISH
con el paquete PUBACK correspondiente. Si el remitente no recibe un paquete PUBACK en un
período de tiempo razonable, el remitente reenvía el paquete PUBLISH. Cuando un receptor recibe un
mensaje con QoS 1, puede procesarlo de inmediato. Por ejemplo, si el receptor es un intermediario, el
intermediario envía el mensaje a todos los clientes suscriptores y luego responde con un paquete
PUBACK.

Si el cliente de publicación envía el mensaje nuevamente, establece un indicador de duplicado (DUP).


En QoS 1, este indicador DUP solo se usa para fines internos y no es procesado por el corredor o el
cliente. El receptor del mensaje envía un PUBACK, independientemente del indicador DUP.

QoS 2: exactamente una vez

QoS 2 es el nivel más alto de servicio en MQTT. Este nivel garantiza que cada mensaje sea recibido
solo una vez por los destinatarios previstos. QoS 2 es el nivel de calidad de servicio más seguro y lento.
La garantía es proporcionada por al menos dos flujos de solicitud / respuesta (un apretón de manos de
cuatro partes) entre el remitente y el receptor. El remitente y el receptor utilizan el identificador de
paquete del mensaje PUBLICAR original para coordinar la entrega del mensaje.
Cuando un receptor obtiene un paquete PUBLICAR QoS 2 de un remitente, procesa el mensaje de
publicación en consecuencia y responde al remitente con un paquete PUBREC que reconoce el paquete
PUBLICAR. Si el remitente no recibe un paquete PUBREC del receptor, envía el paquete PUBLISH
nuevamente con un indicador de duplicado (DUP) hasta que reciba un acuse de recibo.

Una vez que el emisor recibe un paquete PUBREC del receptor, el emisor puede descartar de manera
segura el paquete PUBLISH inicial. El remitente almacena el paquete PUBREC del receptor y
responde con un paquete PUBREL .

Después de que el receptor recibe el paquete PUBREL, puede descartar todos los estados almacenados
y responder con un paquete PUBCOMP (lo mismo ocurre cuando el remitente recibe el PUBCOMP).
Hasta que el receptor complete el procesamiento y envíe el paquete PUBCOMP al remitente, el
receptor almacena una referencia al identificador del paquete PUBLISH original. Este paso es
importante para evitar procesar el mensaje por segunda vez. Después de que el remitente recibe el
paquete PUBCOMP, el identificador del paquete del mensaje publicado queda disponible para su
reutilización.
Cuando se completa el flujo de QoS 2, ambas partes están seguras de que el mensaje se entrega y el
remitente tiene confirmación de la entrega.

Si un paquete se pierde en el camino, el remitente es responsable de retransmitir el mensaje dentro de


un período de tiempo razonable. Esto es igualmente cierto si el remitente es un cliente MQTT o un
intermediario MQTT . El destinatario tiene la responsabilidad de responder a cada mensaje de comando
en consecuencia.

Bueno saber

Algunos aspectos de QoS no son muy obvios a primera vista. Aquí hay algunas cosas a tener en cuenta
cuando usa QoS:

Downgrade de QoS

Como ya mencionamos, la definición de QoS y los niveles entre el cliente que envía (publica) el
mensaje y el cliente que recibe el mensaje son dos cosas diferentes. Los niveles de QoS de estas dos
interacciones también pueden ser diferentes. El cliente que envía el mensaje PUBLICAR al
intermediario define la QoS del mensaje. Sin embargo, cuando el intermediario entrega el mensaje a los
destinatarios (suscriptores), utiliza la QoS que el receptor (suscriptor) definió durante la suscripción.
Por ejemplo, el cliente A es el remitente del mensaje. El cliente B es el receptor del mensaje. Si el
cliente B se suscribe al intermediario con QoS 1 y el cliente A envía el mensaje al intermediario con
QoS 2, el intermediario entrega el mensaje al cliente B (receptor / suscriptor) con QoS 1. El mensaje se
puede entregar más de una vez al cliente SI,porque QoS 1 garantiza la entrega del mensaje al menos
una vez y no impide la entrega múltiple del mismo mensaje.

Los identificadores de paquetes son únicos por cliente

El identificador de paquete que MQTT usa para QoS 1 y QoS 2 es único entre un cliente específico y
un intermediario dentro de una interacción. Este identificador no es único entre todos los clientes. Una
vez que se completa el flujo, el identificador de paquete está disponible para su reutilización. Esta
reutilización es la razón por la cual el identificador de paquete no necesita exceder 65535. No es
realista que un cliente pueda enviar más que este número de mensajes sin completar una interacción.

Mejores prácticas

A menudo se nos pide asesoramiento sobre cómo elegir el nivel de QoS correcto. Aquí hay algunas
pautas que pueden ayudarlo en su proceso de toma de decisiones. La QoS adecuada para usted depende
en gran medida de su caso de uso.
Use QoS 0 cuando …

• Tiene una conexión completa o mayormente estable entre el remitente y el receptor. Un caso de
uso clásico para QoS 0 es conectar un cliente de prueba o una aplicación front-end a un agente
MQTT a través de una conexión por cable.
• No le importa si se pierden algunos mensajes ocasionalmente. La pérdida de algunos mensajes
puede ser aceptable si los datos no son tan importantes o cuando los datos se envían a intervalos
cortos
• No necesita hacer cola de mensajes. Los mensajes solo se ponen en cola para clientes
desconectados si tienen QoS 1 o 2 y una sesión persistente .

Use QoS 1 cuando …

• Necesita recibir todos los mensajes y su caso de uso puede manejar duplicados. El nivel de
calidad de servicio 1 es el nivel de servicio más utilizado porque garantiza que el mensaje
llegue al menos una vez, pero permite múltiples entregas. Por supuesto, su aplicación debe
tolerar duplicados y poder procesarlos en consecuencia.
• No puede soportar la sobrecarga de QoS 2. QoS 1 entrega mensajes mucho más rápido que QoS
2.

Use QoS 2 cuando …

• Es fundamental para su aplicación recibir todos los mensajes exactamente una vez. Este suele
ser el caso si una entrega duplicada puede dañar a los usuarios de aplicaciones o clientes
suscritos. Tenga en cuenta la sobrecarga y que la interacción QoS 2 tarda más tiempo en
completarse.

Cola de mensajes QoS 1 y 2


Todos los mensajes enviados con QoS 1 y 2 se ponen en cola para clientes fuera de línea hasta que el
cliente vuelva a estar disponible. Sin embargo, esta cola solo es posible si el cliente tiene una sesión
persistente .

PARTE 7 Persistent Session and Queuing Messages

Sesión persistente

Para recibir mensajes de un agente MQTT , un cliente se conecta al agente y crea suscripciones a los
temas en los que está interesado. Si la conexión entre el cliente y el intermediario se interrumpe durante
una sesión no persistente, estos temas se pierden y el cliente debe suscribirse nuevamente al volver a
conectarse. Volver a suscribirse cada vez que se interrumpe la conexión es una carga para los clientes
restringidos con recursos limitados. Para evitar este problema, el cliente puede solicitar una sesión
persistente cuando se conecta al intermediario. Las sesiones persistentes guardan toda la información
relevante para el cliente en el intermediario. El clientId que proporciona el cliente cuando establece
conexión con el intermediario identifica la sesión ( más detalles ).
¿Qué se almacena en una sesión persistente?

En una sesión persistente, el intermediario almacena la siguiente información (incluso si el cliente está
fuera de línea). Cuando el cliente se vuelve a conectar, la información está disponible de inmediato.

• Existencia de una sesión (incluso si no hay suscripciones).


• Todas las suscripciones del cliente.
• Todos los mensajes en un flujo de calidad de servicio (QoS) 1 o 2 que el cliente aún no ha
confirmado.
• Todos los mensajes nuevos de QoS 1 o 2 que el cliente perdió mientras estaba desconectado.
• Todos los mensajes de QoS 2 recibidos del cliente que aún no se reconocen por completo.

¿Cómo iniciar o finalizar una sesión persistente?

Cuando el cliente se conecta al intermediario, puede solicitar una sesión persistente. El cliente utiliza
un indicador cleanSession para indicarle al agente qué tipo de sesión necesita:

• Cuando el indicador de sesión limpia se establece en verdadero, el cliente no desea una sesión
persistente. Si el cliente se desconecta por algún motivo, se pierde toda la información y los
mensajes que se pusieron en cola de una sesión persistente anterior.
• Cuando el indicador de sesión limpia se establece en falso, el intermediario crea una sesión
persistente para el cliente. Toda la información y los mensajes se conservan hasta la próxima
vez que el cliente solicite una sesión limpia. Si el indicador de sesión limpia se establece en
falso y el intermediario ya tiene una sesión disponible para el cliente, utiliza la sesión existente
y entrega mensajes en cola previamente al cliente.

Para obtener más información sobre el establecimiento de la conexión entre el cliente y el agente,
consulte la parte 3 de MQTT Essentials .

¿Cómo sabe el cliente si una sesión ya está almacenada?

Desde MQTT 3.1.1, el mensaje CONNACK del intermediario contiene un indicador de presencia de
sesión . Este indicador le dice al cliente si una sesión previamente establecida todavía está disponible
en el intermediario. Para obtener más información sobre el establecimiento de la conexión, consulte la
parte 3 de MQTT Essentials .

Sesión persistente en el lado del cliente

Similar al intermediario, cada cliente MQTT también debe almacenar una sesión persistente. Cuando
un cliente solicita al servidor que retenga los datos de la sesión, el cliente es responsable de almacenar
la siguiente información:

• Todos los mensajes en un flujo de QoS 1 o 2, que el intermediario aún no ha confirmado.


• Todos los mensajes de QoS 2 recibidos del agente que aún no se reconocen por completo.
Mejores prácticas

Aquí hay algunas pautas que pueden ayudarlo a decidir cuándo usar una sesión persistente o una sesión
limpia:

Sesión persistente

• El cliente debe recibir todos los mensajes de un tema determinado, incluso si está fuera de línea.
Desea que el intermediario ponga en cola los mensajes para el cliente y los entregue tan pronto
como el cliente vuelva a estar en línea.
• El cliente tiene recursos limitados. Desea que el intermediario almacene la información de
suscripción del cliente y restablezca la comunicación interrumpida rápidamente.
• El cliente debe reanudar todos los mensajes de publicación de QoS 1 y 2 después de una
reconexión.

Sesión limpia

• El cliente solo necesita publicar mensajes en los temas, el cliente no necesita suscribirse a los
temas. No desea que el intermediario almacene información de sesión o reintente la transmisión
de mensajes QoS 1 y 2.
• El cliente no necesita recibir mensajes que pierde fuera de línea.

¿Cuánto tiempo almacena el corredor los mensajes?

La gente a menudo pregunta cuánto tiempo el corredor almacena la sesión. La respuesta fácil es: el
corredor almacena la sesión hasta que los clientes vuelven a estar en línea y reciben el mensaje. Sin
embargo, ¿qué sucede si un cliente no vuelve a estar en línea durante mucho tiempo? Por lo general, el
límite de memoria del sistema operativo es la restricción principal para el almacenamiento de mensajes.
No hay una respuesta estándar para este escenario. La solución correcta depende de su caso de uso. Por
ejemplo, en HiveMQ ofrecemos la posibilidad de purgar mensajes en cola.

PARTE 8 Retained Messages


Un mensaje retenido es un mensaje MQTT normal con el indicador retenido establecido en verdadero.
El agente almacena el último mensaje retenido y la QoS correspondiente para ese tema. Cada cliente
que se suscribe a un patrón de tema que coincide con el tema del mensaje retenido recibe el mensaje
retenido inmediatamente después de suscribirse. El agente almacena solo un mensaje retenido por
tema.

Si el cliente suscriptor incluye comodines en el patrón de tema al que se suscribe, recibe un mensaje
retenido incluso si el tema del mensaje retenido no coincide exactamente. Aquí hay un ejemplo: el
Cliente A publica un mensaje retenido en mi casa / sala de estar / temperatura . Algún tiempo después,
el cliente B se suscribe a myhome / # . El cliente B recibe el mensaje myhome / livingroom /
temperatura retenida directamente después de suscribirse a myhome / # . El cliente B (el cliente
suscriptor) puede ver que el mensaje es un mensaje retenido porque el intermediario envía mensajes
retenidos con el indicador retenido establecido en verdadero. El cliente puede decidir cómo quiere
procesar los mensajes retenidos.
Los mensajes retenidos ayudan a los clientes recién suscritos a obtener una actualización de
estado inmediatamente después de suscribirse a un tema. El mensaje retenido elimina la espera
de que los clientes de publicación envíen la próxima actualización.

En otras palabras, un mensaje retenido sobre un tema es el último valor positivo conocido . El mensaje
retenido no tiene que ser el último valor, pero debe ser el último mensaje con el indicador retenido
establecido en verdadero.

Es importante comprender que un mensaje retenido no tiene nada que ver con sesiones persistentes .
Una vez que el intermediario almacena un mensaje retenido, solo hay una forma de eliminarlo. Sigue
leyendo para averiguar cómo.

Enviar un mensaje retenido

Desde la perspectiva de un desarrollador, enviar un mensaje retenido es bastante simple y directo.


Simplemente establece el indicador retenido de un mensaje de publicación MQTT en verdadero. Por lo
general, su biblioteca de cliente proporciona una manera fácil de configurar este indicador.

Eliminar un mensaje retenido

También hay una manera muy simple de eliminar el mensaje retenido de un tema: envíe un mensaje
retenido con una carga útil de cero bytes sobre el tema en el que desea eliminar el mensaje retenido
anterior. El intermediario elimina el mensaje retenido y los nuevos suscriptores ya no reciben un
mensaje retenido para ese tema. A menudo, ni siquiera es necesario eliminar, porque cada nuevo
mensaje retenido sobrescribe el anterior.

¿Por qué y cuándo debes usar los mensajes retenidos?

Un mensaje retenido tiene sentido cuando desea que los suscriptores recién conectados reciban
mensajes de inmediato (sin esperar hasta que un cliente de publicación envíe el siguiente
mensaje). Esto es extremadamente útil para las actualizaciones de estado de componentes o
dispositivos en temas individuales. Por ejemplo, el estado del dispositivo1 está en el tema myhome /
devices / device1 / status . Cuando se utilizan mensajes retenidos, los nuevos suscriptores del tema
obtienen el estado (en línea / fuera de línea) del dispositivo inmediatamente después de suscribirse. Lo
mismo es cierto para los clientes que envían datos en intervalos, temperatura, coordenadas GPS y otros
datos. Sin mensajes retenidos, los nuevos suscriptores se mantienen en la oscuridad entre los
intervalos de publicación. El uso de mensajes retenidos ayuda a proporcionar el último buen valor a
un cliente que se conecta de inmediato.
PARTE 9 Last Will and Testament

Última voluntad y testamento


En MQTT, utiliza la función Última voluntad y testamento (LWT) para notificar a otros clientes acerca
de un cliente desconectado sin gracia. Cada cliente puede especificar su último mensaje de voluntad
cuando se conecta a un intermediario. El último mensaje de voluntad es un mensaje MQTT normal con
un tema, indicador de mensaje retenido, QoS y carga útil. El agente almacena el mensaje hasta que
detecta que el cliente se ha desconectado sin gracia. En respuesta a la desconexión sin gracia, el
intermediario envía el mensaje de último testamento a todos los clientes suscritos del tema del mensaje
de último testamento. Si el cliente se desconecta con gracia con un mensaje de DESCONEXIÓN
correcto, el intermediario descarta el mensaje LWT almacenado.

LWT lo ayuda a implementar diversas estrategias cuando la conexión de un cliente se cae (o al menos
informa a otros clientes sobre el estado fuera de línea).

¿Cómo se especifica un mensaje LWT para un cliente?

Los clientes pueden especificar un mensaje LWT en el mensaje CONNECT que inicia la conexión
entre el cliente y el intermediario.

¿Cuándo envía un corredor el mensaje LWT?

De acuerdo con la especificación MQTT 3.1.1 , el intermediario debe distribuir el LWT de un cliente en
las siguientes situaciones:

• El intermediario detecta un error de E / S o falla de la red.


• El cliente no se comunica dentro del período definido Keep Alive.
• El cliente no envía un paquete de DESCONEXIÓN antes de cerrar la conexión de red.
• El intermediario cierra la conexión de red debido a un error de protocolo.
• Escucharemos más sobre el tiempo Keep Alive en la próxima publicación .

Mejores prácticas: ¿cuándo debe usar LWT?

LWT es una excelente manera de notificar a otros clientes suscritos sobre la pérdida inesperada de
conexión de otro cliente. En escenarios del mundo real, LWT a menudo se combina con mensajes
retenidos para almacenar el estado de un cliente sobre un tema específico. Por ejemplo, client1 primero
envía un mensaje CONNECT al intermediario con un lastWillMessage que tiene " Offline " como carga
útil, el indicador lastWillRetain establecido en true y el lastWillTopic establecido en client1 / status . A
continuación, el cliente envía un mensaje PUBLICAR con la carga útil " En línea " y el indicador
retenido establecido en verdadero para el mismo tema ( cliente1 / estado ). Mientras el cliente1
permanezca conectado, los clientes recién suscritos al tema cliente1 / estado recibirán el mensaje " En
línea"Mensaje retenido. Si el cliente1 se desconecta inesperadamente, el agente publica el mensaje
LWT con la carga útil " Sin conexión " como el nuevo mensaje retenido. Los clientes que se suscriben
al tema mientras el cliente1 está desconectado, reciben el mensaje retenido LWT (" Sin conexión ") del
intermediario. Este patrón de mensajes retenidos mantiene a otros clientes actualizados sobre el estado
actual del cliente1 sobre un tema específico.

PARTE 10 Keep Alive and Client Take-Over

El problema de las conexiones TCP medio abiertas

MQTT se basa en el Protocolo de Control de Transmisión (TCP) . Este protocolo garantiza que los
paquetes se transfieran a través de Internet de una manera "confiable, ordenada y con verificación de
errores" . Sin embargo, de vez en cuando, la transferencia entre las partes que se comunican puede
desincronizarse. Por ejemplo, si una de las partes falla o tiene errores de transmisión. En TCP, este
estado de conexión incompleta se denomina conexión medio abierta . El punto importante a recordar es
que un lado de la comunicación continúa funcionando y no se le notifica sobre la falla del otro lado. El
lado que aún está conectado sigue intentando enviar mensajes y espera acuses de recibo.

Como señala Andy Stanford-Clark (el inventor del protocolo MQTT), el problema con las conexiones
entreabiertas aumenta en las redes móviles:

"Aunque en teoría TCP / IP le notifica cuando se rompe un socket, en la práctica,


particularmente en cosas como enlaces móviles y satelitales, que a menudo"
falsifican "TCP por el aire y vuelven a colocar los encabezados en cada extremo,
es bastante posible para un TCP sesión al "agujero negro", es decir, parece estar
abierto todavía, pero de hecho es simplemente arrojar al suelo todo lo que le
escribes ".
MQTT Keep Alive

MQTT incluye una función de mantener vivo que proporciona una solución para el problema de las
conexiones medio abiertas (o al menos hace posible evaluar si la conexión aún está abierta).

Mantener vivo garantiza que la conexión entre el intermediario y el cliente todavía está abierta y que el
intermediario y el cliente son conscientes de estar conectados. Cuando el cliente establece una
conexión con el intermediario, el cliente comunica un intervalo de tiempo en segundos al intermediario.
Este intervalo define el período máximo de tiempo que el agente y el cliente pueden no comunicarse
entre sí.

La especificación MQTT dice lo siguiente :

"Keep Alive ... es el intervalo de tiempo máximo que puede transcurrir entre el
punto en el que el Cliente termina de transmitir un Paquete de Control y el punto
en que comienza a enviar el siguiente. Es responsabilidad del Cliente asegurarse
de que el intervalo entre los paquetes de control que se envían no excede el valor
de Keep Alive. En ausencia de enviar cualquier otro paquete de control, el cliente
DEBE enviar un paquete PINGREQ ".

Siempre que los mensajes se intercambien con frecuencia y no se exceda el intervalo de


mantenimiento, no es necesario enviar un mensaje adicional para establecer si la conexión aún
está abierta.

Si el cliente no envía mensajes durante el período de mantenimiento, debe enviar un paquete


PINGREQ al agente para confirmar que está disponible y para asegurarse de que el agente también esté
disponible.

El intermediario debe desconectar un cliente que no envía un mensaje o un paquete PINGREQ


en una vez y media el intervalo de mantener vivo. Del mismo modo, se espera que el cliente cierre la
conexión si no recibe una respuesta del agente en un período de tiempo razonable.

Mantenga el flujo vivo

Echemos un vistazo más de cerca a los mensajes de mantener vivo. La función mantener vivo utiliza
dos paquetes:

PINGREQ
PINGREQ es enviado por el cliente e indica al corredor que el cliente aún está vivo. Si el cliente no
envía ningún otro tipo de paquetes (por ejemplo, un paquete PUBLICAR o SUSCRIBIR), el cliente
debe enviar un paquete PINGREQ al agente. El cliente puede enviar un paquete PINGREQ en
cualquier momento que desee confirmar que la conexión de red sigue viva. El paquete PINGREQ no
contiene una carga útil.

PINGRESP

Cuando el agente recibe un paquete PINGREQ, debe responder con un paquete PINGRESP para
mostrarle al cliente que todavía está disponible. El paquete PINGRESP tampoco contiene una carga
útil.

Bueno saber
• Si el intermediario no recibe un PINGREQ o cualquier otro paquete de un cliente, el
intermediario cierra la conexión y envía el último testamento y un mensaje de testamento (si el
cliente especificó un LWT).
• Es responsabilidad del cliente MQTT establecer un valor apropiado para mantener vivo. Por
ejemplo, el cliente puede ajustar el intervalo de mantenimiento de vida a su intensidad de señal
actual.
• El máximo de mantener vivo es 18h 12min 15 seg.
• Si el intervalo de mantener vivo es 0, el mecanismo de mantener vivo se desactiva.

Adquisición de clientes

Por lo general, un cliente desconectado intenta volver a conectarse. A veces, el corredor aún tiene una
conexión medio abierta para el cliente. En MQTT, si el intermediario detecta una conexión medio
abierta, realiza una 'toma de control del cliente'. El intermediario cierra la conexión anterior con el
mismo cliente (determinado por el identificador del cliente) y establece una nueva conexión con el
cliente. Este comportamiento garantiza que la conexión medio abierta no impide que el cliente
desconectado restablezca una conexión.

También podría gustarte