Conexões TCP podem morrer em silêncio. Um roteador reinicia, um celular troca de antena, uma entrada da tabela NAT expira — e nenhum dos lados recebe um encerramento limpo. O mecanismo de keep alive do MQTT existe para que tanto o cliente quanto o broker percebam uma conexão morta em um tempo previsível, e para que o broker possa publicar a mensagem Last Will do cliente quando isso acontecer. Este artigo explica exatamente como o keep alive funciona no MQTT 3.1.1 e 5, e como escolher um valor adequado à sua rede.
O que é o intervalo de keep alive
O keep alive é um valor de 16 bits, em segundos, que o cliente envia no seu pacote CONNECT. É uma promessa: "Nunca vou ficar em silêncio por mais tempo que isso." O valor máximo é 65535 segundos (pouco mais de 18 horas), e 0 desativa o mecanismo por completo.
O ponto principal é que o timer vale para qualquer pacote de controle, não apenas pings. Um cliente que publica uma leitura de sensor a cada 10 segundos com keep alive de 60 segundos nunca precisa enviar um ping, porque os pacotes PUBLISH já provam que ele está vivo. Pings só são enviados quando o cliente não tem mais nada a dizer.
PINGREQ e PINGRESP
Quando o período de keep alive está prestes a se esgotar sem que o cliente tenha enviado nada, ele envia um PINGREQ. O broker deve responder com um PINGRESP. Os dois pacotes são minúsculos: apenas um cabeçalho fixo de 2 bytes, sem cabeçalho variável e sem payload.
| Pacote | Direção | Bytes na rede | Finalidade |
|---|---|---|---|
PINGREQ | Cliente → broker | 0xC0 0x00 | Prova que o cliente está vivo; pergunta se o broker está vivo |
PINGRESP | Broker → cliente | 0xD0 0x00 | Prova que o broker e o caminho de volta até o cliente funcionam |
Dois bytes de MQTT não contam a história toda — TCP/IP, registros TLS e, nos navegadores, o enquadramento WebSocket adicionam overhead a cada ping. Se você está dimensionando um plano de dados celular, a calculadora de tamanho de pacote MQTT ajuda a estimar a parte MQTT de cada pacote para que você some o overhead do transporte.
A regra de 1,5×: quando uma conexão é declarada morta
Os dois lados usam o keep alive de formas diferentes:
- Lado do broker — se o broker não receber nenhum pacote de controle do cliente dentro de uma vez e meia o período de keep alive, ele deve fechar a conexão de rede como se a rede tivesse falhado. Com keep alive de 60 segundos, isso significa 90 segundos de silêncio.
- Lado do cliente — se o cliente envia um
PINGREQe não recebe umPINGRESPem um tempo razoável, ele mesmo deve fechar a conexão. As bibliotecas costumam tratar a falta de resposta ao ping até o próximo ciclo de keep alive como falha e começam a reconectar.
Como o broker trata um timeout de keep alive como desconexão anormal, o Last Will do cliente é publicado. É isso que faz funcionar o clássico padrão de "dispositivo offline": defina um will retido offline em devices/42/status, e o broker anuncia a falha em seu nome no máximo 1,5 período de keep alive depois que o dispositivo desaparece.
Server Keep Alive no MQTT 5
No MQTT 3.1.1, o cliente decide o keep alive e o broker precisa aceitá-lo (ou recusar a conexão). O MQTT 5 adiciona a propriedade Server Keep Alive ao CONNACK. Se o broker a incluir, o cliente deve usar o valor do broker em vez do que pediu. Os brokers usam isso para impedir que clientes peçam um keep alive de 0 ou de muitas horas, o que deixaria conexões mortas se acumularem.
O MQTT 5 também torna a falha explícita: antes de fechar, um broker pode enviar um DISCONNECT com o reason code 0x8D (Keep Alive timeout). Você pode consultar esse e todos os outros códigos na referência de reason codes MQTT. Veja MQTT 5 vs 3.1.1 para as outras diferenças do protocolo.
Muitas vezes os brokers também impõem limites do lado do servidor. O Mosquitto, por exemplo, tem a opção max_keepalive: clientes MQTT 5 recebem o valor limitado via Server Keep Alive, enquanto clientes MQTT 3.1.1 que pedem mais podem ser rejeitados.
Configurando o keep alive nos clientes mais comuns
A maioria das bibliotecas usa 60 segundos por padrão. Veja como alterar:
# -k sets the keep alive in seconds
mosquitto_sub -h broker.hivemq.com -t 'testmqtt/ka-demo/#' -k 30 -vimport mqtt from 'mqtt';
const client = mqtt.connect('wss://broker.hivemq.com:8884/mqtt', {
keepalive: 30, // seconds; 0 disables
reconnectPeriod: 2000 // ms between reconnect attempts
});import paho.mqtt.client as mqtt
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.connect("broker.hivemq.com", 1883, keepalive=30)
client.loop_forever()Quer o código completo para a sua linguagem? O gerador de código MQTT produz código de conexão com o keep alive já configurado. Para observar o comportamento ao vivo, conecte o cliente MQTT online com um keep alive curto e deixe-o ocioso.
NAT, firewalls e redes móveis
O keep alive tem uma segunda função que a especificação não menciona: manter os equipamentos intermediários satisfeitos. Gateways NAT, o CGNAT das redes móveis, load balancers e firewalls stateful descartam fluxos TCP ociosos após um timeout. Quando o mapeamento some, o cliente ainda acredita estar conectado, mas nada do que ele envia chega ao broker e nada do que o broker envia chega ao cliente.
- Fique abaixo do menor idle timeout do caminho. Load balancers em nuvem e operadoras móveis costumam usar idle timeouts de poucos minutos, às vezes menos. Um keep alive com folga abaixo disso mantém o mapeamento ativo.
- Não dependa do TCP keepalive. Os padrões de TCP keepalive do sistema operacional geralmente são medidos em horas, lentos demais para proteger uma sessão MQTT.
- Equilibre com a bateria. Cada ping acorda o rádio. Em dispositivos celulares a bateria, intervalos mais longos combinados com uma sessão persistente (para que as mensagens perdidas fiquem na fila) costumam ser o melhor equilíbrio.
- WebSockets não são exceção. Clientes de navegador atrás de proxies enfrentam os mesmos idle timeouts; o keep alive do MQTT funciona da mesma forma em MQTT sobre WebSockets.
Como escolher um valor de keep alive
| Cenário | Keep alive sugerido | Por quê |
|---|---|---|
| Dashboards e serviços de backend em redes estáveis | 30–60 s | Padrão das bibliotecas, pouco overhead, detecção em cerca de um minuto |
| Dispositivos em que o "offline" precisa aparecer rápido | 10–20 s | A mensagem will dispara em cerca de 15–30 s |
| Redes celulares / com muito NAT | Abaixo do menor idle timeout do caminho | Evita conexões semiabertas silenciosas |
| Dispositivos a bateria, com envios pouco frequentes | Vários minutos, ou conectar–publicar–desconectar | Menos despertares do rádio; conte com sessões persistentes |
Solucionando desconexões por keep alive
Se os clientes se desconectam a cada 1,5× keep alive, a causa mais comum é um loop do cliente que não está rodando — por exemplo, o loop de rede do Paho bloqueado por um trabalho demorado dentro de um callback, de modo que nenhum PINGREQ é enviado. Já reconexões frequentes em um intervalo fixo de alguns minutos apontam para um idle timeout em um proxy ou NAT. Para outras causas, veja o guia de erros de conexão MQTT.
Perguntas frequentes
Qual é um bom intervalo de keep alive no MQTT?
Para a maioria dos dispositivos em redes estáveis, 30 a 60 segundos é um padrão sensato. Use valores menores (15 a 30 segundos) quando precisar detectar clientes mortos rapidamente ou ficar abaixo de um timeout de NAT agressivo, e valores maiores em dispositivos a bateria, em que cada despertar do rádio custa energia.
O que acontece quando o keep alive do MQTT expira?
Se o broker não recebe nenhum pacote de controle do cliente dentro de uma vez e meia o intervalo de keep alive, ele fecha a conexão de rede e a trata como uma desconexão anormal. Isso significa que a mensagem Last Will, se houver, é publicada. No MQTT 5, o broker pode antes enviar um DISCONNECT com o reason code 0x8D (Keep Alive timeout).
Definir o keep alive como 0 o desativa?
Sim. Um keep alive de 0 desliga o mecanismo, e o broker nunca desconecta o cliente por inatividade. Raramente é uma boa ideia, porque conexões TCP semiabertas podem então ficar abertas por muito tempo sem que ninguém perceba.