Fundamentos de MQTT

O Modelo Publish Subscribe do MQTT: Desacoplando Dispositivos e Aplicações

O modelo publish subscribe do MQTT permite que dispositivos e aplicações troquem dados sem saber nada uns dos outros. Conheça os três tipos de desacoplamento e teste-os ao vivo com dois clientes no servidor MQTT público broker.connectmq.com.

Diagrama do modelo publish subscribe do MQTT com sensores publicando em um broker que distribui as mensagens para painéis e serviços
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

O modelo publish subscribe do MQTT é o motivo pelo qual um sensor de temperatura, um painel e um serviço de faturamento conseguem compartilhar dados sem nunca saber o endereço uns dos outros. Neste artigo você vai aprender como o pub/sub difere do modelo requisição/resposta, o que os três tipos de desacoplamento significam na prática e vai comprovar cada um deles com duas janelas de terminal conectadas ao servidor MQTT público (gratuito).

Requisição/resposta vs. publish/subscribe

A maioria dos desenvolvedores aprende redes pelo HTTP. Um cliente abre uma conexão com um servidor conhecido, faz uma pergunta e espera a resposta. Esse padrão é simples, mas acopla fortemente as duas partes: o cliente precisa saber o endereço do servidor, o servidor precisa estar no ar naquele exato momento e o cliente fica bloqueado (ou fazendo polling) até algo voltar.

O publish/subscribe quebra esse acoplamento inserindo um intermediário. No MQTT, esse intermediário é o broker. Os clientes nunca falam entre si; falam apenas com o broker:

  • Um publicador envia uma mensagem com um tópico como plant1/line2/press/temperature.
  • Um assinante informa ao broker quais tópicos lhe interessam, opcionalmente com curingas como plant1/+/press/#.
  • O broker compara cada mensagem recebida com todas as assinaturas ativas e encaminha uma cópia para cada correspondência.

Se o papel do servidor no meio ainda é novidade para você, nosso guia sobre o que um broker MQTT faz aborda roteamento, sessões e estado retido com mais detalhes.

Aspecto Requisição/resposta (HTTP) Publish/subscribe do MQTT
Quem conhece quem O cliente conhece o endereço do servidor Os clientes só conhecem o broker
Direção O cliente busca (pull) O broker envia (push) na chegada
Fan-out para muitos leitores Uma requisição por leitor Uma publicação, muitas entregas
Conexão Muitas vezes de curta duração Uma conexão TCP de longa duração
Receptores offline A requisição falha Sessões persistentes podem enfileirar

Os três tipos de desacoplamento no modelo publish subscribe do MQTT

A literatura de pub/sub costuma descrever três dimensões de desacoplamento. Vale separá-las, porque cada uma resolve um problema diferente de IoT.

Desacoplamento de espaço

Publicadores e assinantes não conhecem o endereço IP, o hostname nem mesmo a quantidade uns dos outros. Um sensor publica em site/tank3/level; se zero, uma ou cinquenta aplicações recebem a mensagem é invisível para o sensor. É isso que permite adicionar um novo serviço de análise no ano que vem sem mexer no firmware de milhares de dispositivos já em campo.

Desacoplamento de tempo

Publicador e assinante não precisam estar online ao mesmo tempo. O MQTT oferece dois mecanismos para isso:

  • Mensagens retidas. O broker guarda a última mensagem retida de cada tópico e a entrega imediatamente a qualquer novo assinante. Um painel que inicia às 09:00 ainda vê o estado da válvula publicado às 06:00.
  • Sessões persistentes. Um assinante que se conecta com a flag clean start igual a false (e, no MQTT 5, um session expiry interval) mantém suas assinaturas enquanto está desconectado, e o broker enfileira para ele as mensagens QoS 1 e QoS 2.

O desacoplamento de tempo não é ilimitado. As filas são limitadas pelo session expiry e pelas cotas do broker, então trate-o como um buffer para interrupções curtas, não como armazenamento de longo prazo.

Desacoplamento de sincronização

Nenhum dos lados bloqueia o outro. O publicador entrega a mensagem à biblioteca cliente e segue em frente; a biblioteca cuida das confirmações em segundo plano. Os assinantes recebem mensagens por callbacks, em vez de esperar em um loop. Em um microcontrolador, isso significa que o loop principal continua lendo os sensores enquanto a E/S de rede acontece de forma assíncrona.

Tópicos: o contrato entre publicadores e assinantes

Como não há ligação direta entre as partes, a string do tópico é o único contrato que elas compartilham. Por isso, um bom design de tópicos importa mais no MQTT do que o design de URLs importa no REST:

  1. Vá do geral para o específico: company/site/area/line/device/measurement.
  2. Mantenha os níveis estáveis e significativos para que os curingas continuem úteis.
  3. Nunca coloque segredos ou dados pessoais identificáveis nos nomes dos tópicos.
  4. Não comece tópicos com $; esse prefixo é reservado para tópicos do broker como $SYS.
  5. Separe comandos de telemetria, por exemplo .../cmd/... versus .../telemetry/....

O curinga + corresponde a exatamente um nível e # corresponde a qualquer número de níveis finais. Um historiador pode assinar acme/#, enquanto um supervisor de linha só precisa de acme/izmir/assembly/line4/+/status.

Teste: dois clientes no broker.connectmq.com

Nada faz o modelo fazer sentido mais rápido do que vê-lo acontecer. Instale os clientes de linha de comando do Mosquitto (mosquitto_pub e mosquitto_sub) e abra dois terminais. Escolha um sufixo aleatório para que seus tópicos não colidam com os de outras pessoas no servidor MQTT público. Lembre-se de que ele pode ser lido por todos e serve para testes e protótipos, então não publique nada sensível nem dados de produção.

Passo 1: inicie um assinante

# Terminal A: assinatura com curinga
mosquitto_sub -h broker.connectmq.com -p 1883 -i sub-demo-7f3a \
  -t "connectmq/demo/7f3a/#" -v

Passo 2: publique a partir de outro cliente

# Terminal B: publica duas leituras
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-demo-7f3a \
  -t "connectmq/demo/7f3a/room1/temperature" -m "21.4"
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-demo-7f3a \
  -t "connectmq/demo/7f3a/room2/temperature" -m "19.8"

O terminal A imprime as duas mensagens com seus tópicos. O publicador nunca soube onde estava o assinante: isso é desacoplamento de espaço.

Passo 3: comprove o desacoplamento de tempo com uma mensagem retida

Pare o assinante com Ctrl+C. Agora publique um valor retido enquanto ninguém está ouvindo:

mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-demo-7f3a \
  -t "connectmq/demo/7f3a/door/state" -m "open" -r

Inicie o assinante novamente. Ele recebe imediatamente connectmq/demo/7f3a/door/state open, embora a mensagem tenha sido enviada enquanto estava offline. Para limpar, publique um payload retido vazio com -r -n.

Passo 4: fan-out

Abra um terceiro terminal com outro assinante (use um client ID diferente, como sub2-demo-7f3a). Publique uma vez e os dois assinantes recebem a mensagem. Uma publicação, muitas entregas, e o código do publicador não mudou.

Um assinante programático em Python

O mesmo modelo em código mostra o desacoplamento de sincronização: o callback dispara sempre que chegam dados, enquanto seu programa continua livre para fazer outras tarefas.

import time
import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
PREFIX = "connectmq/demo/7f3a"

def on_connect(client, userdata, flags, reason_code, properties):
    print("Connected:", reason_code)
    client.subscribe(f"{PREFIX}/#", qos=1)

def on_message(client, userdata, msg):
    print(f"{msg.topic} -> {msg.payload.decode()} (retained={msg.retain})")

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="py-sub-7f3a")
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, 1883, keepalive=60)
client.loop_start()

try:
    while True:
        # Sua aplicação continua trabalhando; as mensagens chegam em segundo plano.
        time.sleep(5)
        client.publish(f"{PREFIX}/heartbeat", str(int(time.time())), qos=1)
except KeyboardInterrupt:
    client.loop_stop()
    client.disconnect()

Por que o pub/sub combina tão bem com IoT

  • Enlaces instáveis. Dispositivos em rede celular ou Wi-Fi, como os de uma fazenda ou de uma mineradora, caem com frequência. Sessões persistentes e QoS 1/2 permitem que eles se atualizem sem lógica de retentativa personalizada. O guia de níveis de QoS do MQTT explica as garantias de entrega em detalhes.
  • Muitos consumidores por dado. A mesma leitura de vibração pode alimentar um painel, um script de alertas e um historiador. Cada um assina de forma independente.
  • Apenas conexões de saída. Os dispositivos abrem uma conexão com o broker; nada precisa se conectar ao dispositivo. Isso é muito mais amigável a NAT e firewalls do que rodar um servidor HTTP em cada sensor.
  • Pacotes pequenos. O cabeçalho fixo pode ter dois bytes, o que mantém baixo o tempo de rádio e o consumo do plano de dados.

Armadilhas comuns e como evitá-las

Nenhum assinante não é um erro. Se você publica em um tópico sem assinantes, o broker aceita e descarta a mensagem (a menos que seja retida). Às vezes os desenvolvedores supõem que uma mensagem perdida é um problema de rede quando, na verdade, é um erro de digitação no tópico. Assine # sob o seu prefixo durante a depuração.

Client IDs duplicados. Dois clientes com o mesmo ID se derrubam mutuamente em loop. Cada conexão precisa de um ID único.

Curingas amplos demais em produção. Um serviço que assina # recebe tudo, inclusive tráfego que não consegue processar. Restrinja as assinaturas aos níveis de que você precisa.

Esperar respostas. O pub/sub não tem resposta embutida. Se você precisa de semântica de requisição/resposta, o MQTT 5 acrescenta response topic e correlation data, abordados na nossa visão geral dos recursos do MQTT 5.

Ordenação entre tópicos. O MQTT preserva a ordem por tópico para uma dada QoS a partir de um mesmo publicador, mas não entre tópicos diferentes. Inclua um timestamp ou número de sequência nos payloads quando a ordem importar.

Da demonstração à produção

O servidor MQTT público é perfeito para experimentos, mas é compartilhado e pode ser lido por todos. Para dispositivos reais, você precisa de autenticação, TLS na porta 8883 e um namespace isolado só seu. Um broker MQTT gerenciado como o ConnectMQ oferece exatamente isso: crie um broker no portal, copie o usuário, a senha e o client ID gerados e aponte o mesmo código para a porta 8883 com TLS. O ConnectMQ é compatível com MQTT 3.1.1 e 5.0, então mensagens retidas, session expiry e shared subscriptions funcionam como este artigo descreve. Para uma visão mais ampla do protocolo, comece pelo nosso tutorial completo de MQTT ou leia como o MQTT funciona no nível dos pacotes.

Comece a usar o ConnectMQ

Pronto para levar seu protótipo pub/sub para um broker privado? Cadastre-se em app.connectmq.com e crie um broker Serverless gratuito em poucos minutos, sem cartão de crédito. O cliente MQTT no navegador e o explorador de tópicos ao vivo do ConnectMQ permitem acompanhar publicações e assinaturas sem instalar nada.

Perguntas frequentes

O publish subscribe do MQTT é a mesma coisa que uma fila de mensagens?

Não exatamente. No MQTT, cada assinante correspondente recebe sua própria cópia de cada mensagem, enquanto uma fila clássica entrega cada mensagem a um único consumidor. As shared subscriptions do MQTT 5 adicionam balanceamento de carga no estilo fila quando você precisa.

Um cliente pode publicar e assinar ao mesmo tempo?

Sim. Uma única conexão MQTT pode publicar em alguns tópicos e assinar outros, e é assim que a maioria dos dispositivos recebe comandos enquanto envia telemetria.

O que acontece com as mensagens quando ninguém está inscrito?

O broker as descarta, a menos que a mensagem seja retida; nesse caso, o último valor retido de cada tópico é armazenado para futuros assinantes.

Os publicadores sabem quantos assinantes receberam uma mensagem?

Não. No MQTT, as confirmações ocorrem apenas entre o cliente e o broker, e é exatamente isso que mantém publicadores e assinantes desacoplados.

Artigos relacionados

Por que Seu Cliente MQTT Fica Desconectando (e Como Corrigir)

Loops de reconexão estão entre os problemas mais comuns do MQTT. Conheça as cinco causas habituais, de client IDs duplicados a timeouts de keep alive e pacotes grandes demais, e siga um fluxo de diagnóstico que identifica a sua.

9 min de leitura

Quem Inventou o MQTT? A História dos Oleodutos à IoT

O MQTT foi inventado em 1999 por Andy Stanford-Clark, da IBM, e Arlen Nipper, da Arcom, para monitorar oleodutos via satélite. Acompanhe sua trajetória até o open source, a OASIS, a ISO e os brokers MQTT gerenciados na nuvem de hoje.

8 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.