Entendendo Tópicos e Curingas do MQTT com Exemplos Práticos

O que são tópicos MQTT?

Um tópico MQTT é uma string codificada em UTF-8 que serve como base para o roteamento de mensagens no protocolo MQTT. Assim como um caminho de URL, ele utiliza a barra / para criar uma estrutura hierárquica:

chat/sala/1
sensor/10/temperatura
sensor/+/temperatura
sensor/#

Os tópicos MQTT não precisam ser criados previamente. Um cliente MQTT os cria automaticamente ao publicar ou assinar um tópico, e também não é necessário removê-los explicitamente. Para evitar ambiguidades e facilitar a compreensão, é recomendado não iniciar ou terminar tópicos com /, como em /chat ou chat/.

No diagrama abaixo, temos um fluxo simples de publicação e assinatura MQTT. O APP 1, ao assinar o tópico sensor/2/temperatura, receberá as mensagens publicadas pelo Sensor 2 nesse mesmo tópico.

Curingas em tópicos MQTT

Os curingas MQTT incluem o curinga de nível único + e o curinga de vários níveis #. Eles são usados principalmente para que um cliente assine múltiplos tópicos de uma só vez.

Atenção: Curingas só podem ser usados em assinaturas, nunca em publicações.

Curinga de nível único (+)

O sinal de mais (+, U+002B) é um curinga que corresponde a um único nível hierárquico do tópico. Ao usá-lo, o curinga deve ocupar um nível inteiro, por exemplo:

+          Válido
sensor/+   Válido
sensor/+/temperatura  Válido
sensor+    Inválido (não ocupa um nível inteiro)

Se um cliente assinar o tópico sensor/+/temperatura, ele receberá mensagens dos seguintes tópicos:

sensor/1/temperatura
sensor/2/temperatura
...
sensor/n/temperatura

No entanto, não corresponderá a estes:

sensor/temperatura
sensor/quarto/1/temperatura

Curinga de vários níveis (#)

O sinal de cerquilha (#, U+0023) é um curinga que corresponde a qualquer número de níveis em um tópico. Ele representa o nível pai e todos os seus subníveis. Ao usá-lo, o curinga deve ocupar um nível inteiro e ser o último caractere do tópico, por exemplo:

#                  Válido (corresponde a todos os tópicos)
sensor/#           Válido
sensor/quarto#     Inválido (não ocupa um nível inteiro)
sensor/#/temperatura  Inválido (não é o último caractere)

Se um cliente assinar o tópico sensor/#, ele receberá mensagens dos seguintes tópicos:

sensor
sensor/temperatura
sensor/1/temperatura

Tópicos iniciados com $

Tópicos de sistema

Tópicos que começam com $SYS/ são chamados de tópicos de sistema. Eles são usados para obter informações sobre o estado do servidor MQTT, estatísticas de mensagens, eventos de conexão/desconexão de clientes, entre outros. Atualmente, o protocolo MQTT não define um padrão rígido para $SYS/, mas a maioria dos servidores MQTT segue essa convenção.

Por exemplo, o servidor EMQX permite obter o estado do cluster através dos seguintes tópicos.

Assinatura compartilhada

A assinatura compartilhada é um recurso introduzido no MQTT 5.0 para balancear a carga de assinaturas entre múltiplos assinantes. No MQTT 5.0, os tópicos de assinatura compartilhada começam com $share.

Embora o protocolo MQTT tenha introduzido a assinatura compartilhada apenas na versão 5.0, o EMQX já a suporta desde a versão 3.1.1.

No diagrama abaixo, três assinantes usam uma assinatura compartilhada para o mesmo tópico $share/g/topic. Aqui, topic é o nome real do tópico que eles estão assinando, e $share/g/ é o prefixo da assinatura compartilhada, onde g/ é o nome do grupo (pode ser qualquer string UTF-8).

Design de tópicos em diferentes cenários

Casa inteligente

Suponha que usamos sensores para monitorar temperatura, umidade e qualidade do ar no quarto, na sala e na cozinha. Podemos projetar os seguintes tópicos:

minhacasa/quarto/temperatura
minhacasa/quarto/umidade
minhacasa/quarto/qualidadedoar
minhacasa/sala/temperatura
minhacasa/sala/umidade
minhacasa/sala/qualidadedoar
minhacasa/cozinha/temperatura
minhacasa/cozinha/umidade
minhacasa/cozinha/qualidadedoar

Ao assinar minhacasa/quarto/+, recebemos dados de temperatura, umidade e qualidade do ar do quarto. Assinando minhacasa/+/temperatura, obtemos a temperatura dos três cômodos. Já minhacasa/# nos dá todos os dados.

Estações de recarga para veículos elétricos

O formato do tópico de uplink da estação é ocpp/cp/${cid}/notify/${action}, e o de downlink é ocpp/cp/${cid}/reply/${action}.

  • ocpp/cp/cp001/notify/bootNotification — A estação publica uma solicitação de inicialização neste tópico ao se conectar.
  • ocpp/cp/cp001/notify/startTransaction — Publica uma solicitação de recarga aqui.
  • ocpp/cp/cp001/reply/bootNotification — A estação deve assinar este tópico antes de se conectar para receber a resposta de inicialização.
  • ocpp/cp/cp001/reply/startTransaction — A estação assina este tópico antes de solicitar uma recarga para receber a resposta.

Mensagens instantâneas

  • chat/usuario/${user_id}/inboxChat individual: Ao fazer login, o usuário assina este tópico de caixa de entrada para receber mensagens de amigos. Para responder, basta substituir o user_id pelo ID do amigo.
  • chat/grupo/${group_id}/inboxChat em grupo: Após entrar em um grupo, o usuário assina este tópico para receber mensagens do grupo. Para responder, publica-se diretamente neste tópico.
  • req/usuario/${user_id}/addSolicitação de amizade: Publica-se uma solicitação de amizade aqui (onde user_id é o ID do destinatário). O destinatário assina este tópico (com seu próprio ID) para receber solicitações.
  • resp/usuario/${user_id}/addResposta à solicitação de amizade: Antes de adicionar um amigo, o solicitante assina este tópico (com seu próprio ID) para receber a resposta. Para responder, o destinatário publica aqui (com o ID do solicitante) indicando se aceita ou não.
  • usuario/${user_id}/stateStatus online: Os usuários podem assinar este tópico para saber o status online de seus amigos.

Perguntas frequentes sobre tópicos MQTT

Existem limites de profundidade ou comprimento para tópicos?

O protocolo MQTT especifica que o comprimento do tópico é de dois bytes, portanto, um tópico pode ter no máximo 65.535 caracteres. Recomanda-se que a profundidade do tópico não ultrapasse 7 níveis.

O servidor impõe um limite no número de tópicos?

Diferentes servidores de mensagens têm suporte variado para o número máximo de tópicos. Atualmente, a configuração padrão do EMQX não limita o número de tópicos, mas quanto mais tópicos, mais memória do servidor será consumida. Considerando que geralmente há muitos dispositivos conectados ao Broker MQTT, recomenda-se que um cliente assine no máximo 10 tópicos.

O desempenho de assinaturas com curinga é igual ao de assinaturas normais?

Assinaturas com curinga têm desempenho inferior a assinaturas normais e consomem mais recursos do servidor. O usuário deve escolher o tipo de assinatura com base em suas necessidades reais.

Um mesmo tópico pode ser usado simultaneamente com assinatura compartilhada e assinatura normal?

Sim, é possível, mas não é recomendado.

Quais são as recomendações comuns para o uso de tópicos MQTT?

  • Evite usar # para assinar todos os tópicos.
  • Evite iniciar ou terminar tópicos com /, como em /chat ou chat/.
  • Evite incluir espaços ou caracteres especiais não ASCII nos tópicos.
  • Dentro de um mesmo nível hierárquico, recomenda-se o uso de sublinhado _ ou hífen - para conectar palavras (ou usar nomenclatura CamelCase).

Publicado em 7-25 18:36