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:
- Vá do geral para o específico:
company/site/area/line/device/measurement. - Mantenha os níveis estáveis e significativos para que os curingas continuem úteis.
- Nunca coloque segredos ou dados pessoais identificáveis nos nomes dos tópicos.
- Não comece tópicos com
$; esse prefixo é reservado para tópicos do broker como$SYS. - 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.



