Fundamentos de MQTT

Tópicos $SYS do MQTT: O Que os Tópicos de Sistema do Broker Revelam

Um guia prático da árvore de topics $SYS: de onde ela vem, por que os curingas a ignoram, o que brokers no estilo Mosquitto publicam ali e como acompanhar o estado de conexão de clientes no ConnectMQ.

Ilustração dos tópicos sys mqtt se ramificando de um broker em estatísticas de conexões, clientes e mensagens
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

Os tópicos SYS do MQTT formam o ramo $SYS/... da árvore de topics, onde o broker publica informações sobre si mesmo em vez de dados da aplicação. Neste artigo você vai aprender de onde vem essa convenção, por que uma assinatura simples em # nunca os mostra, o que um broker típico expõe ali e como usar o único topic de sistema que o ConnectMQ publica para acompanhar o estado de conexão dos clientes.

O que são os tópicos SYS do MQTT?

A especificação MQTT reserva os topics que começam com $ para uso específico do broker. Os clientes não devem publicar dados da aplicação neles, e a especificação deixa o conteúdo totalmente a cargo da implementação. Com o passar dos anos, $SYS/ virou o prefixo de fato para a telemetria do broker: tempo de atividade, versão, número de clientes conectados, contadores de mensagens e bytes e dados administrativos semelhantes.

A expressão importante é "de fato". Não existe uma lista padrão de topics $SYS, nem um formato padrão de payload, nem garantia de que um determinado broker publique algum deles. O Mosquitto popularizou uma árvore grande, outros brokers publicam um subconjunto ou um layout diferente, e muitos brokers MQTT gerenciados substituem a maior parte disso por dashboards e APIs. Trate cada topic $SYS como um detalhe de implementação do broker específico ao qual você está conectado.

Por que uma assinatura em # não os mostra

Isso surpreende quase todo mundo na primeira vez. Se você se inscreve em #, recebe todas as mensagens de aplicação do broker, mas nada de $SYS. Isso é proposital. A especificação MQTT no mqtt.org determina que um filtro de topic que começa com curinga (# ou +) não deve corresponder a nomes de topic que começam com $.

A regra protege os assinantes "pega-tudo" comuns de serem inundados com estatísticas do broker e evita que ferramentas que espelham # republiquem dados de sistema por acidente. Para ler os topics de sistema, você precisa indicar o prefixo $SYS explicitamente:

#                  -> application topics only, never $SYS
$SYS/#             -> everything under $SYS (if the broker allows it)
$SYS/broker/+/+    -> a specific depth under $SYS/broker
+/broker/uptime    -> does NOT match $SYS/broker/uptime

O mesmo raciocínio vale para as regras de curingas dos topics MQTT em geral: os curingas funcionam nível a nível, e o nível inicial com $ simplesmente fica de fora da correspondência por curinga na primeira posição.

Uma árvore $SYS típica (exemplo com Mosquitto)

O Mosquitto é a referência mais comum, então é uma boa forma de ver o que os topics de sistema podem conter. Com a configuração padrão, ele publica um instantâneo dos seus contadores a cada poucos segundos. O intervalo é controlado no mosquitto.conf:

# mosquitto.conf
# Publica atualizações $SYS a cada 10 segundos (0 desativa as atualizações periódicas)
sys_interval 10

Uma seleção dos topics que você verá em uma instância local do Mosquitto:

Topic Significado
$SYS/broker/version String de versão do broker
$SYS/broker/uptime Segundos desde que o broker iniciou
$SYS/broker/clients/connected Clientes conectados no momento
$SYS/broker/clients/disconnected Sessões persistentes cujo cliente está offline
$SYS/broker/messages/received Total de mensagens recebidas desde o início
$SYS/broker/messages/sent Total de mensagens enviadas desde o início
$SYS/broker/subscriptions/count Assinaturas ativas
$SYS/broker/retained messages/count Retained messages armazenadas
$SYS/broker/load/messages/received/1min Média móvel de mensagens recebidas
$SYS/broker/bytes/received Total de bytes recebidos

Para acompanhá-los no seu próprio broker Mosquitto, coloque o topic entre aspas para que o shell não expanda $SYS:

mosquitto_sub -h localhost -p 1883 -i sys-watcher-01 -t '$SYS/#' -v

A maioria dos valores é publicada como retained message, então um novo assinante recebe o instantâneo mais recente imediatamente, em vez de esperar o próximo intervalo. Os contadores são zerados quando o broker reinicia, o que importa se você os coloca em gráfico: uma queda para zero significa uma reinicialização, não uma hora tranquila.

Armadilhas comuns com dados $SYS

  • Presumir portabilidade. Um dashboard construído sobre os topics $SYS do Mosquitto quebra no momento em que você migra para outro broker. Mantenha a lógica de parsing em um único lugar.
  • Esquecer o shell. No bash, "$SYS/#" com aspas duplas expande $SYS para uma variável vazia e você acaba se inscrevendo em /#. Use aspas simples.
  • Expor publicamente. Em um broker auto-hospedado, os topics de sistema revelam o número de clientes e as versões. Restrinja-os com as regras de autorização do broker se ele for acessível pela internet.
  • Consultar rápido demais. Um sys_interval muito curto adiciona tráfego com pouco valor. De dez a sessenta segundos é mais do que suficiente para gráficos operacionais.

Tópicos SYS do MQTT em um broker gerenciado

Em um broker MQTT gerenciado, normalmente você não precisa de uma árvore $SYS grande, porque o operador já coleta as métricas do broker e as mostra para você. Essa é a abordagem do ConnectMQ. Informações no nível do broker, como conexões e tráfego, são apresentadas no dashboard do portal, e o explorador de topics ao vivo permite ver quais topics estão ativos, então não é preciso fazer parsing de contadores a partir de topics de sistema.

Ele publica exatamente um topic de sistema:

$SYS/broker/connection/{clientId}/state

Esse topic informa o estado de conexão de um client ID específico. É a parte dos dados $SYS de que o código da aplicação realmente precisa: "o dispositivo X está online agora?" Todo o resto, como contagem de clientes e taxas de mensagens, pertence ao monitoramento, e não ao seu fluxo de dados MQTT.

Acompanhando o estado de conexão de um cliente

O exemplo abaixo usa o paho-mqtt 2.x em Python para se inscrever no topic de estado de um dispositivo no seu broker privado. Substitua os placeholders pelas credenciais geradas no portal e defina DEVICE_ID com o client ID do dispositivo que você quer acompanhar.

import ssl
import paho.mqtt.client as mqtt

BROKER = "YOUR_BROKER_HOST"      # exibido no portal
PORT = 8883
DEVICE_ID = "YOUR_DEVICE_CLIENT_ID"
STATE_TOPIC = f"$SYS/broker/connection/{DEVICE_ID}/state"

def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code.is_failure:
        print(f"Connect failed: {reason_code}")
        return
    print("Connected, subscribing to", STATE_TOPIC)
    client.subscribe(STATE_TOPIC, qos=1)

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

def on_message(client, userdata, msg):
    print(f"{msg.topic} -> {msg.payload.decode(errors='replace')}")

client = mqtt.Client(
    mqtt.CallbackAPIVersion.VERSION2,
    client_id="YOUR_CLIENT_ID",
    protocol=mqtt.MQTTv5,
)
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set(cert_reqs=ssl.CERT_REQUIRED)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message

client.connect(BROKER, PORT, keepalive=60)
client.loop_forever()

Execute o script e depois desligue e religue o dispositivo ou pare o cliente dele. Você verá o topic de estado mudar conforme o dispositivo se desconecta e se reconecta. Antes de escrever a lógica de parsing, observe o payload real no cliente MQTT do portal, que roda no navegador, para que o seu código corresponda ao que o broker envia e não ao que você imagina.

Estado $SYS versus Last Will

Talvez você já acompanhe a presença com uma mensagem de Last Will and Testament. As duas abordagens se complementam:

Abordagem Quem publica Ponto forte Limitação
Last Will mais mensagem retida "online" O dispositivo e o broker em nome dele Funciona em qualquer broker; topic e payload são seus O dispositivo precisa configurá-la corretamente; um cliente mal configurado nunca informa nada
$SYS/broker/connection/{clientId}/state O broker Não exige código no dispositivo; reflete o que o broker realmente vê Layout de topic específico do broker

Um padrão sensato é manter o Last Will para consumidores da aplicação que já entendem a sua árvore de topics e usar o topic de estado do broker para ferramentas de operação e para verificar se dispositivos sem Will estão se comportando bem. O guia sobre status online de dispositivos MQTT detalha o padrão baseado em Will.

Checklist de monitoramento sem uma grande árvore $SYS

Se você vem de um broker auto-hospedado em que os gráficos do Grafana eram alimentados por $SYS, veja como cobrir as mesmas necessidades em um broker MQTT gerenciado:

  1. Contagem de conexões e tráfego. Use o dashboard do broker no portal em vez de $SYS/broker/clients/connected.
  2. Quais topics estão vivos. Use o explorador de topics ao vivo em vez de se inscrever em # a partir de um notebook.
  3. Presença por dispositivo. Inscreva-se em $SYS/broker/connection/{clientId}/state para os client IDs que interessam, ou use um Last Will.
  4. Condições de limite sobre os dados. Configure regras de alerta no portal para valores como temperatura ou pressão e revise o log de alertas.
  5. Histórico de métricas de longo prazo. Execute seu próprio assinante (Telegraf, um pequeno serviço em Python ou Node-RED) que grave os dados necessários no seu banco de séries temporais.
  6. Atenção às cotas. Fique de olho no reason code 0x97 (quota exceeded) do MQTT 5 nos logs dos clientes; ele indica que um limite do plano foi atingido.

Testando no servidor MQTT público

Se você só quer experimentar a estrutura de topics, o servidor MQTT público (gratuito) em broker.connectmq.com aceita conexões anônimas com qualquer client ID único e não vazio. Lembre-se de que a área pública pode ser lida por todos, então use um prefixo único e nunca envie dados sensíveis ou de produção:

# Terminal 1: inscreva-se no seu próprio prefixo de demonstração
mosquitto_sub -h broker.connectmq.com -p 1883 -i sys-demo-sub-7f3a \
  -t 'connectmq/demo/7f3a/#' -v

# Terminal 2: publique uma mensagem de teste
mosquitto_pub -h broker.connectmq.com -p 1883 -i sys-demo-pub-7f3a \
  -t 'connectmq/demo/7f3a/hello' -m 'hi'

Repare que a assinatura # no terminal 1 vê a sua mensagem, mas nada sob $SYS, exatamente como a especificação exige. Para uma visão mais ampla de como topics, assinaturas e o broker se encaixam, o tutorial de MQTT é uma boa próxima leitura, e as convenções de nomenclatura de topics MQTT mostram como manter a sua própria árvore tão organizada quanto a árvore de sistema de um broker.

Comece a usar o ConnectMQ

Quer métricas do broker sem fazer parsing de contadores $SYS? Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito. Em poucos minutos você recebe credenciais geradas, um dashboard, um explorador de topics ao vivo e o topic $SYS/broker/connection/{clientId}/state para presença por dispositivo.

Perguntas frequentes

Por que a assinatura em # não mostra as mensagens $SYS?

A especificação MQTT diz que filtros de topic que começam com curinga não devem corresponder a topics que começam com $. Inscreva-se explicitamente em $SYS/# se o seu broker publicar topics de sistema e permitir que você os leia.

Os tópicos SYS do MQTT são padronizados?

Não. Apenas a reserva dos topics com prefixo $ é padronizada. Os nomes dos topics, os payloads e os intervalos de atualização variam entre brokers, então o código que os lê é específico do broker.

Qual topic $SYS o ConnectMQ publica?

O ConnectMQ publica $SYS/broker/connection/{clientId}/state, que informa o estado de conexão de um cliente. Métricas do broker, como conexões e tráfego, são mostradas no dashboard do portal.

Posso publicar minhas próprias mensagens em topics $SYS?

Não deveria. O prefixo $ é reservado para o broker, e a maioria dos brokers rejeita ou ignora publicações de clientes ali. Coloque seus próprios dados de status na árvore de topics da sua aplicação.

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.