Fundamentos de MQTT

QoS Máximo no MQTT e Rebaixamento de Assinaturas

O QoS que você pede nem sempre é o QoS que você recebe. Entenda como o QoS efetivo é calculado, como os brokers anunciam um QoS máximo e concedem níveis menores nas assinaturas, e como verificar o que sua conexão realmente usa.

Publicador em QoS 2 e assinante em QoS 1 se encontrando em um broker, mostrando o rebaixamento do QoS máximo MQTT
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 QoS máximo MQTT é a parte da qualidade de serviço que mais surpreende as pessoas: você pode publicar em QoS 2 e ainda assim receber a mensagem em QoS 0. O nível realmente usado em uma entrega depende do publicador, do assinante e dos limites do próprio broker. Neste artigo você vai entender como o QoS efetivo é calculado, como os brokers anunciam e impõem um máximo e como testar exatamente o que a sua conexão recebe.

O QoS é negociado por salto

O MQTT tem três níveis de QoS: 0 (at most once, no máximo uma vez), 1 (at least once, pelo menos uma vez) e 2 (exactly once, exatamente uma vez). Se eles forem novidade para você, comece por níveis de QoS do MQTT explicados.

O ponto-chave é que o QoS não é fim a fim. Uma mensagem percorre dois saltos separados:

  1. Do publicador ao broker, no QoS que o publicador escolheu para aquele PUBLISH.
  2. Do broker a cada assinante, em um QoS que o broker calcula para aquela assinatura.

Cada salto tem seu próprio handshake. O PUBACK do publicador vem do broker, e não do assinante, então um publicador nunca sabe se algum assinante recebeu a mensagem.

Como o QoS efetivo é calculado

Para cada assinante, o broker entrega no menor de dois valores: o QoS do PUBLISH recebido e o QoS concedido para a assinatura correspondente.

QoS do publish QoS da assinatura QoS entregue
0 2 0
1 0 0
1 2 1
2 1 1
2 2 2

Duas consequências importam na prática:

  • Assinar em QoS 2 não eleva nada. Se um sensor publica em QoS 0, todo assinante recebe em QoS 0, independentemente do que pediu.
  • Um assinante pode rebaixar o QoS de propósito. Um dashboard que só se importa com o valor mais recente pode assinar em QoS 0 uma telemetria publicada em QoS 1, economizando confirmações no seu próprio link.

Se um filtro de assinatura se sobrepõe a outro (por exemplo, plant/# e plant/line1/+), o broker pode entregar a mensagem uma vez no maior QoS correspondente ou, no MQTT 5, uma vez por assinatura, dependendo da implementação. Evite assinaturas sobrepostas com QoS diferentes sempre que puder.

Como os brokers limitam o QoS

Um broker não é obrigado a suportar todos os níveis para todos os clients. Ele tem dois mecanismos para informar isso.

QoS concedido no SUBACK. Quando um client assina, o broker responde com um SUBACK contendo o QoS concedido para cada filtro. Ele pode conceder um nível menor que o solicitado. No MQTT 3.1.1 os códigos de retorno são 0, 1, 2 ou 0x80 para falha; no MQTT 5 são reason codes em que 0x00, 0x01 e 0x02 significam QoS concedido 0, 1 e 2. Um client bem escrito verifica esse valor em vez de presumir que o pedido foi atendido.

Maximum QoS no CONNACK (MQTT 5). Um broker MQTT 5 que não suporta QoS 2, ou QoS 1 e 2, inclui uma propriedade Maximum QoS no CONNACK. Se a propriedade estiver ausente, o QoS 2 é suportado. Um client que publica acima do máximo anunciado está violando o protocolo, e o broker o desconecta com o reason code 0x9B (QoS not supported). No MQTT 3.1.1 não existe essa propriedade, então os clients descobrem da pior maneira.

Os brokers limitam o QoS por bons motivos: o QoS 2 exige mais estado armazenado e quatro pacotes por mensagem em cada salto, o que pesa em uma infraestrutura compartilhada e multi-tenant.

Testando o QoS máximo MQTT no servidor MQTT público

O servidor MQTT público em broker.connectmq.com suporta QoS de 0 a 2, então é um bom lugar para ver os rebaixamentos causados pela combinação de publish e subscribe. A flag -d faz as ferramentas do Mosquitto imprimirem os pacotes do protocolo, incluindo o QoS concedido no SUBACK.

Terminal 1, assinando com pedido de QoS 1:

mosquitto_sub -d -h broker.connectmq.com -p 1883 -i mq-sub-u3x7 -q 1 \
  -t 'connectmq/demo/u3x7/#' -F 'qos=%q %t %p'

Na saída de debug, procure uma linha como Client mq-sub-u3x7 received SUBACK seguida de Subscribed (mid: 1): 1. O número final é o QoS concedido.

Terminal 2, publicando em cada nível:

for q in 0 1 2; do
  mosquitto_pub -h broker.connectmq.com -p 1883 -i mq-pub-u3x7 -q $q \
    -t connectmq/demo/u3x7/test -m "published at qos $q"
done

O terminal 1 imprime qos=0, qos=1 e qos=1. O publish em QoS 2 foi rebaixado para 1 no caminho até este assinante, porque foi isso que a assinatura pediu. Reinicie o assinante com -q 2 e a terceira linha passa a ser qos=2.

Verificando o QoS concedido e o máximo no código

Este script com paho-mqtt 2.x se conecta com MQTT 5, imprime o Maximum QoS anunciado pelo broker, se houver, assina em QoS 2 e imprime o que foi concedido:

import uuid
import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
TOPIC = "connectmq/demo/u3x7/check"

def on_connect(client, userdata, flags, reason_code, properties):
    max_qos = getattr(properties, "MaximumQoS", None)
    if max_qos is None:
        print("CONNACK: no Maximum QoS property, QoS 2 supported")
    else:
        print(f"CONNACK: broker maximum QoS is {max_qos}")
    client.subscribe(TOPIC, qos=2)

def on_subscribe(client, userdata, mid, reason_code_list, properties):
    rc = reason_code_list[0]
    if rc.is_failure:
        print("subscription refused:", rc)
    else:
        print(f"SUBACK: requested 2, granted {rc.value}")
    client.disconnect()

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=f"qoscheck-{uuid.uuid4().hex[:8]}",
                     protocol=mqtt.MQTTv5)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.connect(BROKER, 1883, keepalive=30)
client.loop_forever()

Rode o mesmo script contra o seu broker de produção, com suas credenciais reais, antes de depender de um nível de QoS. Leva segundos e elimina o achismo.

QoS em retained messages e mensagens de will

A mesma regra do mínimo vale para mensagens que o broker envia por iniciativa própria. Uma retained message é armazenada com o QoS em que foi publicada, e um novo assinante a recebe no menor valor entre esse QoS e o QoS concedido à sua assinatura. Um Last Will é publicado no QoS de will definido no CONNECT, e cada assinante, mais uma vez, o recebe no menor dos dois. Se o QoS máximo do broker for inferior ao QoS de will que você solicita, um broker MQTT 5 pode recusar a conexão com o reason code 0x9B; por isso, mantenha o QoS do will dentro do limite anunciado.

Checklist prático

  1. Decida o QoS por topic com base no custo de uma mensagem perdida ou duplicada.
  2. Publique nesse QoS; os assinantes não conseguem elevá-lo.
  3. Verifique o QoS concedido no SUBACK e registre em log quando ele for menor que o solicitado.
  4. Com MQTT 5, leia o Maximum QoS do CONNACK e limite seus publishes a ele.
  5. Projete os consumidores para o QoS que você realmente recebe: idempotentes no QoS 1 (veja mensagens duplicadas no MQTT) e tolerantes a lacunas no QoS 0.
  6. Evite assinaturas sobrepostas com QoS diferentes no mesmo client.

Solução de problemas de QoS

Client desconectado logo após publicar. Se o reason code for 0x9B, você publicou acima do máximo do broker. Reduza o QoS ou migre para um plano ou broker que o suporte. A lista completa de códigos está em reason codes do MQTT.

O assinante recebe QoS 0 embora tenha assinado em QoS 1. O publicador está usando QoS 0. Corrija na origem.

A biblioteca informa sucesso, mas mensagens se perdem. Algumas bibliotecas ignoram o QoS concedido. Verifique o SUBACK você mesmo, como no script acima.

O QoS 2 é lento. Cada mensagem precisa de quatro pacotes por salto. Para telemetria de alta taxa, QoS 1 com deduplicação geralmente oferece melhor throughput.

As regras normativas estão na especificação OASIS MQTT 5.0, nas seções sobre as propriedades do SUBACK e do CONNACK.

Limites de QoS nos planos do ConnectMQ

O ConnectMQ é explícito quanto ao QoS em cada plano. O plano Serverless gratuito suporta QoS até 1, o plano Serverless pago acrescenta o QoS 2, junto com mensagens maiores e shared subscriptions, e as opções Dedicated, BYOC e Self Managed Enterprise oferecem um cluster isolado. O servidor MQTT público permite QoS de 0 a 2 para experimentos, não para dados de produção. Rode o script de verificação com suas credenciais do ConnectMQ para confirmar o que sua conexão informa. Se você está comparando fornecedores, nossa visão geral de um broker MQTT gerenciado e o tutorial de MQTT são boas próximas leituras.

Comece a usar o ConnectMQ

Crie um broker gratuitamente em app.connectmq.com no plano Serverless, sem cartão de crédito. Comece com QoS 0 e 1 e depois passe para o plano pago para ter QoS 2 quando a carga do seu broker MQTT na nuvem precisar de entrega exactly-once.

Perguntas frequentes

O que é QoS efetivo no MQTT?

É o QoS usado para entregar uma mensagem a um assinante: o menor entre o QoS do publish e o QoS concedido à assinatura.

Um assinante pode receber um QoS maior do que o usado pelo publicador?

Não. Uma mensagem publicada em QoS 0 é sempre entregue em QoS 0, independentemente da assinatura.

Como sei qual é o QoS máximo do broker?

No MQTT 5, leia a propriedade Maximum QoS no CONNACK; se ela estiver ausente, o QoS 2 é suportado. No MQTT 3.1.1, verifique o QoS concedido no SUBACK.

O que acontece se eu publicar acima do QoS máximo?

Um broker MQTT 5 desconecta o client com o reason code 0x9B, QoS not supported.

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.