Fundamentos de MQTT

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.

Gráfico de um dispositivo caindo e se reconectando repetidamente para mostrar por que um cliente MQTT fica desconectando
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

Se o seu cliente MQTT fica desconectando, a causa quase sempre é uma de cinco coisas: dois clients compartilhando um client ID, um timeout de keep alive, a rede derrubando silenciosamente conexões ociosas, um pacote que o broker não aceita ou um limite de plano ou de taxa. Este guia explica como reconhecer cada uma pelos sintomas e logs e percorre um fluxo de diagnóstico que leva você rapidamente à correção.

Comece pelo padrão das desconexões

Antes de mudar qualquer configuração, observe como as desconexões acontecem. O momento em que ocorrem diz muito:

Padrão Causa mais provável
Dois dispositivos se revezam desconectando a cada poucos segundos Client ID duplicado
Desconexão em intervalo regular, aproximadamente 1,5 x keep alive Keep alive não está sendo atendido
Desconexão após vários minutos ociosos, só em certas redes Timeout de inatividade de NAT ou firewall
Desconexão logo após publicar uma mensagem específica Pacote grande demais ou topic inválido
Desconexão quando o tráfego dispara Limite de taxa ou cota
Desconexão imediatamente após cada conexão Erro de autorização ou de assinatura

Descubra também qual lado fecha a conexão. Com MQTT 5, um fechamento iniciado pelo broker vem com um pacote DISCONNECT e um reason code. Com MQTT 3.1.1, o broker simplesmente fecha o socket. Se puder, mude o client para MQTT 5 enquanto depura; o reason code muitas vezes responde à pergunta na hora. A referência de reason codes do MQTT lista todos eles.

Causa 1: client IDs duplicados

A especificação MQTT diz que, se um client se conecta com um client ID que já está conectado, o broker deve desconectar o client existente. Se os dois clients têm reconexão automática ativada, eles se derrubam mutuamente para sempre. No MQTT 5, o client que perde recebe o reason code 0x8E Session taken over.

Isso acontece com mais frequência do que você imagina:

  • Firmware com client ID fixo no código gravado em vários dispositivos.
  • Um serviço escalado para duas réplicas com a mesma configuração.
  • Um desenvolvedor rodando o mesmo script em dois terminais.
  • Uma ferramenta MQTT de desktop deixada aberta com o ID que seu dispositivo usa.

Solução: derive os client IDs de algo único, como endereço MAC, número de série ou hostname, e nunca compartilhe um ID entre processos. O guia de client ID MQTT aborda padrões de nomenclatura. Em um broker MQTT gerenciado que emite client IDs junto com as credenciais, use uma conexão por ID emitido.

Causa 2: timeouts de keep alive

O keep alive é uma promessa do client: "você terá notícias minhas pelo menos a cada N segundos". Se o broker não recebe nada por 1,5 vez esse intervalo, ele fecha a conexão, com o motivo 0x8D Keep Alive timeout no MQTT 5. O client envia PINGREQ quando não tem mais nada a enviar, mas só se o seu loop de rede estiver rodando.

Formas comuns de quebrar isso:

  • Chamar uma função bloqueante longa, como time.sleep(120) ou uma requisição HTTP lenta, na mesma thread que roda o loop MQTT.
  • No Arduino, esquecer de chamar mqtt.loop() com frequência ou usar delay() por minutos seguidos.
  • Definir um keep alive muito curto, como 5 segundos, em um link celular de alta latência.
  • Ciclos de deep sleep mais longos que o intervalo de keep alive, sem uma desconexão limpa.

Solução: rode o loop de rede em uma thread em segundo plano (loop_start() no Paho; o MQTT.js faz isso automaticamente), mantenha o trabalho bloqueante fora dessa thread e escolha um keep alive de 30 a 120 segundos para a maioria das implantações. O guia do intervalo de keep alive explica como ajustá-lo.

Causa 3: timeouts de inatividade de NAT e firewall

Redes móveis, roteadores domésticos e firewalls corporativos rastreiam conexões TCP e as derrubam silenciosamente após um período de inatividade. Nem o client nem o broker são avisados. O client só descobre o problema na próxima vez que tenta enviar algo, e o broker só quando o keep alive expira.

O sinal característico é que as desconexões acontecem na rede celular ou em um local específico, mas não na sua rede de desenvolvimento. Solução: defina o keep alive abaixo do timeout de inatividade da rede, para que o tráfego de PINGREQ mantenha o mapeamento ativo. Se uma operadora derruba conexões ociosas após alguns minutos, um keep alive de 60 segundos é um ponto de partida razoável.

Causa 4: pacotes grandes demais ou inválidos

Os brokers fecham a conexão quando recebem um pacote que não podem aceitar. Gatilhos típicos:

  • Payload acima do tamanho máximo de mensagem do broker. Clients MQTT 5 veem 0x95 Packet too large; clients 3.1.1 simplesmente perdem a conexão. Veja o guia do limite de tamanho de mensagem MQTT.
  • Publicar em um topic que contém + ou #. Wildcards só são válidos em assinaturas.
  • UTF-8 inválido em um nome de topic, produzido pela concatenação de strings com dados binários.
  • Uso indevido de topic alias após uma reconexão no MQTT 5.

Solução: registre em log o topic e o tamanho do payload antes de cada publish e verifique se a desconexão vem depois de uma mensagem específica. A mesma mensagem grande demais muitas vezes é reenviada após a reconexão, o que cria um loop.

Causa 5: limites de taxa e cotas

Brokers compartilhados e brokers MQTT gerenciados se protegem com limites. Publicar mais rápido que o permitido, abrir mais conexões do que o seu plano permite ou exceder um número de assinaturas pode causar recusas ou desconexões. No MQTT 5, procure 0x96 Message rate too high e 0x97 Quota exceeded.

No servidor MQTT público (gratuito) em broker.connectmq.com, pensado para testes e protótipos, cada client está limitado a 10 mensagens por segundo, 10 assinaturas e 64 KB por mensagem. Brokers privados têm limites por plano; o plano Serverless gratuito, por exemplo, permite até 25 conexões e mensagens de 256 KB.

Um fluxo de diagnóstico que funciona

  1. Ative os logs do client. No Paho, client.enable_logger(); nas ferramentas do Mosquitto, -d; no MQTT.js, defina DEBUG=mqttjs*.
  2. Conecte-se com MQTT 5 e registre o reason code e a Reason String de cada DISCONNECT.
  3. Registre os timestamps das conexões e desconexões e compare o intervalo com o seu keep alive.
  4. Verifique o lado do broker. Observe o estado de conexão do client ID no broker e se outra conexão com o mesmo ID aparece no mesmo momento.
  5. Reproduza com um client mínimo. Rode o mosquitto_sub com as mesmas credenciais, na mesma rede. Se ele continuar conectado, o problema está na sua aplicação.
  6. Mude uma coisa de cada vez: client ID, keep alive, tamanho do payload, taxa de publicação.

Aqui está um client Python mínimo que registra tudo o que você precisa para os passos 1 a 3:

import time
import paho.mqtt.client as mqtt

started = time.time()

def ts():
    return f"[{time.time() - started:7.1f}s]"

def on_connect(client, userdata, flags, reason_code, properties):
    print(ts(), "CONNECT", reason_code, "session_present:", flags.session_present)
    client.subscribe("connectmq/demo/5a3c/#", qos=1)

def on_disconnect(client, userdata, flags, reason_code, properties):
    reason = getattr(properties, "ReasonString", "") if properties else ""
    print(ts(), "DISCONNECT", reason_code, f"(0x{reason_code.value:02X})", reason)

client = mqtt.Client(
    mqtt.CallbackAPIVersion.VERSION2,
    client_id="disconnect-debug-5a3c",
    protocol=mqtt.MQTTv5,
)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.reconnect_delay_set(min_delay=1, max_delay=60)
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_forever(retry_first_connection=True)

Para acompanhar a visão que o broker tem de um client a partir de outro terminal, assine o topic de estado de conexão dele:

mosquitto_sub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
  -u YOUR_USERNAME -P YOUR_PASSWORD -i YOUR_MONITOR_CLIENT_ID \
  -t '$SYS/broker/connection/YOUR_CLIENT_ID/state' -v

Coloque o topic entre aspas simples para que o shell não expanda $SYS. O guia de topics $SYS do MQTT explica o que mais você pode monitorar dessa forma. Como o broker vincula client IDs às credenciais, a conexão de monitoramento precisa do seu próprio client ID válido; o client MQTT integrado ao navegador no portal é uma alternativa fácil para uma olhada rápida.

Lógica de reconexão que não piora as coisas

A reconexão automática é essencial, mas uma implementação descuidada transforma um problema em vários:

  • Use backoff exponencial com jitter para que uma frota não se reconecte toda ao mesmo tempo após uma queda.
  • Não tente de novo em erros de autorização. Os códigos 0x86 e 0x87 não se resolvem sozinhos, e repetidas falhas de login podem fazer seu IP ser bloqueado.
  • Assine novamente no on_connect, e não uma única vez na inicialização, a menos que você dependa de uma sessão persistente.
  • Use um Last Will para que outros sistemas saibam quando um dispositivo cai inesperadamente. Veja MQTT Last Will and Testament.

Diagnostique desconexões com o ConnectMQ

O ConnectMQ oferece uma visibilidade do lado do broker que instalações auto-hospedadas muitas vezes não têm. O dashboard e a visualização de dispositivos do portal mostram quais clients estão conectados, o explorador de topics ao vivo mostra o que eles publicam e o topic $SYS/broker/connection/{clientId}/state permite que suas próprias ferramentas acompanhem as mudanças de conexão. Clients MQTT 5 recebem reason codes para violações de cota e de protocolo, então você vê por que uma desconexão aconteceu em vez de adivinhar. Para entender o que um broker MQTT faz durante a vida de uma conexão, veja nosso artigo explicativo, ou o tutorial de MQTT para o protocolo completo.

Tenha conexões estáveis com o ConnectMQ

Um broker MQTT gerenciado tira a disponibilidade do broker da sua lista de preocupações para que você se concentre no comportamento dos clients. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, e teste sua lógica de reconexão contra limites reais antes de lançar. Compare as opções no nosso guia sobre o cenário de brokers MQTT na nuvem.

Perguntas frequentes

Por que meu cliente MQTT desconecta a cada poucos segundos?

A causa mais comum é outro client usando o mesmo client ID. Cada conexão derruba a outra, e as duas se reconectam automaticamente. Dê a cada client um ID único.

Que valor de keep alive devo usar?

Entre 30 e 120 segundos atende à maioria das implantações. Use um valor abaixo do timeout de inatividade da sua rede e garanta que o loop de rede do client rode continuamente para que o PINGREQ seja de fato enviado.

Como sei se foi o broker ou o client que fechou a conexão?

Conecte-se com MQTT 5. Se o broker a fechou, o client recebe um pacote DISCONNECT com um reason code; se o socket simplesmente caiu, o client informa um erro de rede sem reason code.

Uma mensagem grande pode causar desconexões?

Sim. Se um pacote excede o tamanho máximo do broker, o broker fecha a conexão, e se o client reenvia a mesma mensagem depois de reconectar, ele desconecta de novo. Compare os tamanhos de payload com o limite do seu broker.

Artigos relacionados

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

MQTT vs CoAP: Pub/Sub sobre TCP vs Requisição/Resposta sobre UDP

MQTT e CoAP miram dispositivos IoT com recursos limitados, mas seguem abordagens opostas: pub/sub com broker sobre TCP versus requisição/resposta RESTful sobre UDP. Veja como eles se comparam e quando usar cada um.

9 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.