Fundamentos de MQTT

MQTT 3.1.1 vs 5.0: O Que Mudou e Vale a Pena Atualizar?

Uma comparação prática entre MQTT 3.1.1 e 5.0 cobrindo mudanças de comportamento do protocolo, suporte em bibliotecas client e um checklist de migração passo a passo para atualizar uma frota mista de forma gradual.

Duas versões de um pacote MQTT lado a lado com os novos campos de propriedades destacados, ilustrando MQTT 3.1.1 vs 5.0
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

MQTT 3.1.1 vs 5.0 é a questão de versão que toda equipe enfrenta quando um projeto cresce além do protótipo: o protocolo mais novo compensa a migração, e dispositivos antigos e novos conseguem coexistir? Este guia compara como as duas versões se comportam na rede e na prática, lista quais bibliotecas client populares suportam MQTT 5 e traz um checklist de migração para atualizar uma frota mista, um grupo de clients por vez.

Um Breve Histórico

O MQTT 3.1.1 se tornou padrão OASIS em 2014 e ainda é a versão mais implantada. É pequeno, estável e suportado por praticamente toda biblioteca client e todo dispositivo. O MQTT 5.0 veio em seguida como padrão OASIS em 2019. Ele manteve o mesmo modelo central, com topics, níveis de QoS, retained messages e Last Will, e adicionou os recursos que grandes implantações vinham construindo à mão: erros mais claros, expiração, controle de fluxo, metadados e balanceamento de carga. Não existiu uma versão 4; o byte de nível de protocolo do 3.1.1 é 4 e o do 5.0 é 5, e é por isso que as bibliotecas muitas vezes chamam o 3.1.1 de "protocol version 4".

A boa notícia para a migração é que um broker pode atender as duas versões ao mesmo tempo. Cada client declara sua versão no pacote CONNECT, e as mensagens fluem entre clients 3.1.1 e 5.0 nos mesmos topics.

MQTT 3.1.1 vs 5.0 Lado a Lado

Comportamento MQTT 3.1.1 MQTT 5.0
Relato de erros Return codes de 0 a 5 no CONNACK; a maioria das outras falhas apenas fecha a conexão Reason codes em CONNACK, PUBACK, SUBACK, UNSUBACK, DISCONNECT e outros, mais reason strings opcionais
Duração da sessão Flag clean session: para sempre ou nunca Clean start mais session expiry interval em segundos
Duração da mensagem Mensagens esperam indefinidamente nas sessões Message expiry interval por mensagem
Consumidores com balanceamento de carga Não padronizado Shared subscriptions com $share/group/filter
Overhead do topic Topic completo em todo PUBLISH Topic alias substitui o topic por um inteiro
Metadados Apenas no payload User properties, content type, payload format indicator
Requisição/resposta Apenas por convenção Response topic e correlation data
Controle de fluxo Nenhum padronizado Receive maximum, maximum packet size
Desconexão pelo servidor O servidor fecha o socket em silêncio O servidor envia DISCONNECT com um reason code
Opções de assinatura Apenas QoS No local, retain as published, retain handling, subscription identifiers
Mensagem de will Enviada imediatamente na desconexão abrupta Will delay interval opcional
Autenticação Usuário e senha Mais autenticação estendida via pacote AUTH
Capacidades do servidor Implícitas O servidor pode anunciar QoS máximo, disponibilidade de retain, keep alive imposto, client ID atribuído

As Mudanças Que Mais Importam na Prática

Reason codes. No 3.1.1, se um broker rejeita uma publicação por causa de uma cota ou permissão, muitas vezes o client só vê a conexão cair e precisa adivinhar o motivo. No MQTT 5 o broker pode dizer por quê, por exemplo 0x97 (quota exceeded) ou 0x87 (not authorized). Só isso já encurta drasticamente a depuração. A referência de reason codes do MQTT lista todos eles.

Expiração de sessão e de mensagem. Com o 3.1.1, uma sessão persistente vive até o client voltar, o que pode significar um broker guardando mensagens para dispositivos desativados há meses. O MQTT 5 permite que o client diga "mantenha minha sessão por 10 minutos" e que os publicadores digam "este comando não serve para nada depois de 30 segundos". Veja session expiry interval no MQTT para dicas de ajuste.

Shared subscriptions. Várias instâncias de um serviço de backend podem assinar $share/workers/orders/+/new, e o broker distribui as mensagens entre elas. Antes do MQTT 5, isso exigia extensões específicas do broker ou uma fila separada.

User properties e requisição/resposta. Metadados como uma versão de schema ou um trace ID podem viajar em propriedades em vez de ser embutidos em cada payload, e fluxos de requisição/resposta ganham um response topic e correlation data padronizados.

Para um tour recurso por recurso com exemplos, leia recursos do MQTT 5.

O Que Não Muda

Sintaxe de topics e wildcards, os três níveis de QoS, retained messages, Last Will, keep alive, portas e TLS funcionam da mesma forma. Os payloads continuam sendo bytes opacos. Um assinante 3.1.1 recebe mensagens publicadas por um client 5.0; ele apenas não vê as propriedades do MQTT 5. Essa compatibilidade é o que torna possível uma atualização gradual.

Suporte em Bibliotecas Client

Plataforma Biblioteca Suporte a MQTT 5
Python paho-mqtt 2.x Sim, passe protocol=mqtt.MQTTv5
Node.js e navegadores MQTT.js v5 Sim, defina protocolVersion: 5 (o padrão é 4)
Go Eclipse Paho paho.mqtt.golang Não, apenas 3.1.1
Go Eclipse Paho paho.golang Sim, apenas MQTT 5
Java Eclipse Paho Java (pacote mqttv5), HiveMQ MQTT Client Sim
.NET MQTTnet Sim
ESP32 (ESP-IDF) esp-mqtt Sim, quando o suporte a MQTT 5 está habilitado na configuração de build
Arduino PubSubClient, AsyncMqttClient Não, apenas 3.1.1
CLI mosquitto_pub e mosquitto_sub Sim, com -V mqttv5

As versões das bibliotecas mudam, então confirme na documentação oficial antes de se comprometer. O padrão a observar: bibliotecas de servidor e de gateway geralmente suportam MQTT 5, enquanto muitas bibliotecas populares para microcontroladores ainda são apenas 3.1.1. Esse é o principal motivo pelo qual as frotas acabam mistas.

Usando Recursos do MQTT 5 no Código

Este exemplo em Python se conecta com MQTT 5, pede uma sessão de 10 minutos, publica um comando com expiração de 30 segundos e user properties e imprime os reason codes. Ele roda contra o servidor MQTT público (gratuito), que suporta as duas versões e expiração de sessão de até 30 minutos; use-o apenas para testes, nunca para dados de produção.

import time
import uuid

import paho.mqtt.client as mqtt
from paho.mqtt.packettypes import PacketTypes
from paho.mqtt.properties import Properties

PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:8]}"

def on_connect(client, userdata, flags, reason_code, properties):
    print("CONNACK:", reason_code, "| session present:", flags.session_present)
    client.subscribe(f"{PREFIX}/cmd/#", qos=1)

def on_subscribe(client, userdata, mid, reason_code_list, properties):
    print("SUBACK:", [str(rc) for rc in reason_code_list])

def on_message(client, userdata, msg):
    props = msg.properties
    user_props = getattr(props, "UserProperty", None)
    expiry = getattr(props, "MessageExpiryInterval", None)
    print(f"{msg.topic} {msg.payload.decode()} user={user_props} expiry={expiry}")

def on_publish(client, userdata, mid, reason_code, properties):
    print("PUBACK:", reason_code)

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=f"v5-demo-{uuid.uuid4().hex[:8]}",
                     protocol=mqtt.MQTTv5)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message
client.on_publish = on_publish

connect_props = Properties(PacketTypes.CONNECT)
connect_props.SessionExpiryInterval = 600  # mantém a sessão por 10 minutos

client.connect("broker.connectmq.com", 1883, keepalive=30,
               clean_start=False, properties=connect_props)
client.loop_start()
time.sleep(1)

pub_props = Properties(PacketTypes.PUBLISH)
pub_props.MessageExpiryInterval = 30
pub_props.UserProperty = [("schema", "v2"), ("source", "ops-console")]
pub_props.ContentType = "application/json"

client.publish(f"{PREFIX}/cmd/pump7", '{"action":"stop"}', qos=1,
               properties=pub_props)
time.sleep(2)
client.loop_stop()
client.disconnect()

Para ver a interoperabilidade, rode um assinante 3.1.1 no mesmo topic em outro terminal. Ele recebe o payload, mas não as propriedades.

mosquitto_sub -h broker.connectmq.com -p 1883 -V mqttv311 \
  -i v311-check-$RANDOM -t "connectmq/demo/+/cmd/#" -v

Checklist de Migração

Use este checklist para passar do 3.1.1 para o 5.0 sem uma virada de chave única.

  1. Confirme o suporte do broker. Seu broker precisa aceitar as duas versões simultaneamente. O ConnectMQ aceita, então clients antigos e novos podem compartilhar topics durante a transição.
  2. Faça o inventário de clients por biblioteca. Liste cada tipo de dispositivo, gateway e serviço com sua biblioteca MQTT e versão. Marque quais podem migrar para MQTT 5 hoje.
  3. Atualize primeiro os serviços de backend. São eles que mais ganham (reason codes, shared subscriptions, controle de fluxo) e os mais fáceis de reimplantar.
  4. Substitua a lógica de clean session. Mapeie clean_session=True para clean start com session expiry 0, e clean_session=False para clean start false com uma expiração explícita em vez de "para sempre".
  5. Trate os reason codes. Registre reason codes e reason strings em CONNACK, SUBACK, PUBACK e DISCONNECT, e pare de tentar novamente em códigos que não admitem nova tentativa, como "not authorized".
  6. Ainda não dependa de propriedades para dados críticos. Enquanto houver assinantes 3.1.1, tudo de que eles precisam deve continuar no payload ou no topic.
  7. Introduza a expiração de forma deliberada. Adicione message expiry primeiro a comandos e alertas sensíveis ao tempo, em que uma entrega atrasada é prejudicial.
  8. Adote shared subscriptions para consumidores escalados horizontalmente e remova qualquer deduplicação caseira entre instâncias.
  9. Atualize gateways e dispositivos por último, por grupo (por exemplo, uma planta ou uma usina por vez), acompanhando o estado das conexões e as taxas de erro depois de cada onda.
  10. Teste o básico de novo. Reconexão, Last Will, estado retido e sessões persistentes devem se comportar como antes; o checklist de testes MQTT cobre cada um deles.

Vale a Pena Atualizar?

Para projetos novos, comece com MQTT 5 onde suas bibliotecas o suportarem. Para frotas existentes, atualize serviços e gateways agora e os dispositivos quando houver oportunidade, por exemplo no próximo ciclo de firmware. Há pouca razão para apressar dispositivos restritos cuja biblioteca é apenas 3.1.1, porque um broker que fala as duas versões elimina a pressão. O tutorial de MQTT cobre os fundamentos comuns se você estiver integrando novos membros à equipe.

Um broker MQTT gerenciado que suporta as duas versões torna a transição tranquila. O ConnectMQ aceita clients MQTT 3.1.1 e 5.0 no mesmo broker e suporta recursos do MQTT 5 como session expiry, message expiry, topic alias, response topic, retained messages e reason codes, com shared subscriptions no plano Serverless pago.

Atualize no ConnectMQ no Seu Ritmo

Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, conecte um dispositivo 3.1.1 e um serviço MQTT 5 e confirme que eles interoperam antes de planejar o restante da migração.

Perguntas frequentes

O MQTT 3.1.1 e o MQTT 5.0 são compatíveis?

No mesmo broker, sim. Os clients escolhem a versão no momento da conexão, e as mensagens fluem entre versões. Um assinante 3.1.1 simplesmente não recebe as propriedades do MQTT 5.

Qual é o maior benefício do MQTT 5?

Para a maioria das equipes, são os reason codes, porque as falhas deixam de ser desconexões silenciosas. Expiração de sessão e de mensagem e shared subscriptions vêm logo atrás.

Por que o MQTT 3.1.1 é chamado de protocol version 4?

O pacote CONNECT carrega um byte de nível de protocolo, que é 4 no MQTT 3.1.1 e 5 no MQTT 5.0. Bibliotecas como o MQTT.js usam esse número em suas opções.

Preciso atualizar meus dispositivos ESP32 para MQTT 5?

Não necessariamente. Se você usa uma biblioteca 3.1.1 como a PubSubClient, os dispositivos podem continuar funcionando com um broker que suporta as duas versões enquanto o seu backend adota o MQTT 5.

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.