En MQTT, le topic est le seul lien entre éditeurs et abonnés. Il n’y a ni files d’attente ni exchanges à configurer — le broker compare simplement le topic de chaque message à tous les filtres d’abonnement. La conception des topics est donc la colonne vertébrale de votre système : elle détermine ce à quoi les clients peuvent s’abonner, la façon dont les permissions s’expriment et la facilité avec laquelle vous ajouterez de nouveaux consommateurs plus tard.
Les bases des topics
Un nom de topic est une chaîne UTF-8 composée de niveaux séparés par une barre oblique :
building-a/floor-3/room-12/temperature
vehicles/truck-0042/gps
acme/devices/sensor-17/status- Les topics sont sensibles à la casse.
Home/Kitchenethome/kitchensont deux topics différents. - Aucun enregistrement nécessaire. Un topic existe dès que quelqu’un publie dessus.
- Chaque caractère compte. Une barre oblique initiale crée un premier niveau vide :
/home/kitchenn’est donc pas identique àhome/kitchen. Les espaces sont autorisés mais sèment une confusion sans fin. - Taille. Un nom de topic doit comporter au moins un caractère et au plus 65 535 octets, et ne doit pas contenir le caractère nul.
Les jokers (wildcards) : + et #
Les abonnés utilisent des filtres de topic, qui peuvent contenir deux jokers. Les éditeurs utilisent toujours des noms de topic concrets — un joker dans un PUBLISH est une violation du protocole.
Joker à un niveau : +
+ correspond à exactement un niveau. Il doit occuper un niveau entier (sensor+ est invalide) mais peut apparaître n’importe où, et plusieurs fois.
| Filtre | Correspond à | Ne correspond pas à |
|---|---|---|
home/+/temperature | home/kitchen/temperature | home/kitchen/oven/temperature |
+/+/status | acme/sensor-17/status | acme/status |
home/+ | home/kitchen | home, home/kitchen/light |
Joker multiniveau : #
# correspond à un nombre quelconque de niveaux — y compris zéro — et doit être le dernier caractère du filtre, seul sur son niveau. home/# correspond à home/kitchen, à home/kitchen/light/state et aussi au parent home lui-même. Des filtres comme home/#/light ou home# sont invalides.
Un # seul s’abonne à tous les topics du broker (sauf les topics $). C’est pratique pour déboguer votre propre broker privé, mais sur un broker public vous serez submergé par le trafic des autres.
$SYS et les autres topics $
Les topics qui commencent par $ sont réservés au broker. Le plus courant est $SYS/, où de nombreux brokers (Mosquitto, EMQX et d’autres) publient des statistiques comme le nombre de clients connectés, les débits de messages et l’uptime. Les topics exacts dépendent du broker — la spécification ne réserve que le préfixe.
Les jokers placés au premier niveau ne correspondent pas aux topics $ : # et +/monitor ne livreront jamais de messages $SYS/.... Abonnez-vous explicitement :
mosquitto_sub -h test.mosquitto.org -t '$SYS/broker/clients/connected' -vMQTT 5 ajoute un autre préfixe réservé : les abonnements partagés utilisent $share/<group>/<filter>. Tous les abonnés d’un même groupe se partagent le flux, chaque message n’étant remis qu’à un seul membre — une façon simple de répartir la charge entre consommateurs. Voir MQTT 5 vs 3.1.1 pour les autres nouveautés de MQTT 5, comme les topic aliases.
Concevoir une hiérarchie de topics
Une bonne hiérarchie va du général au particulier, de sorte que les jokers placés à la fin sélectionnent des groupes cohérents. Un schéma courant :
<org-or-app>/<site>/<device-type>/<device-id>/<measurement-or-channel>
acme/berlin/thermostat/th-0193/temperature
acme/berlin/thermostat/th-0193/setpoint/set
acme/berlin/thermostat/th-0193/statusAvec cette organisation :
acme/berlin/#fournit à un tableau de bord de site tout ce qui concerne Berlin.acme/+/thermostat/+/temperaturefournit à un service d’analyse toutes les mesures des thermostats.acme/berlin/thermostat/th-0193/#fournit le flux complet d’un seul appareil.
Bonnes pratiques
- Ne commencez pas par une barre oblique. Elle ajoute un niveau vide inutile.
- Utilisez des minuscules, de l’ASCII et des tirets. Évitez les espaces et la casse mixte ; ils provoquent des non-correspondances subtiles.
- Mettez l’ID de l’appareil ou du client dans le topic. Cela facilite le contrôle d’accès par client (de nombreux brokers savent substituer le client ID ou le nom d’utilisateur dans des patterns d’ACL).
- Séparez données, commandes et état. Par exemple
.../temperaturepour la télémétrie,.../setpoint/setpour les commandes et.../statuspour un état retenu (retained) ou une présence via Last Will. - Gardez des topics courts mais parlants. Le topic est envoyé avec chaque message (sauf si vous utilisez les topic aliases de MQTT 5) : des noms très longs coûtent de la bande passante sur des liaisons contraintes.
- N’encodez pas de données dans le topic. Les valeurs ont leur place dans le payload ; un topic par valeur crée un nombre illimité de topics et une multitude de messages retenus.
- Versionnez votre schéma s’il est susceptible d’évoluer. Un préfixe comme
v1/permet aux anciens et aux nouveaux appareils de coexister pendant une migration. - Évitez les abonnements trop larges en production. S’abonner à
#dans un service backend fait de chaque message du broker son problème.
Erreurs fréquentes avec les topics
- S’attendre à ce que
a/+corresponde àa. Ce n’est pas le cas —+exige la présence d’un niveau. Utiliseza/#si vous voulez aussi le parent. - Les barres obliques finales.
home/kitchen/possède un dernier niveau vide et constitue un topic différent dehome/kitchen. - Les abonnements qui se chevauchent. Si un client s’abonne à la fois à
home/#et àhome/+/temperature, la spécification autorise le broker à livrer une seule copie ou une copie par abonnement correspondant : certains brokers vous enverront donc des doublons. Gardez des abonnements disjoints autant que possible. - Mélanger les formats d’ID. Si certains appareils publient sous
Sensor_17et d’autres soussensor-17, chaque filtre et chaque règle d’ACL doit gérer les deux. Normalisez les IDs dès le provisionnement. - Utiliser les topics comme une base de données. Les brokers sont optimisés pour le routage, pas pour les requêtes. Si vous avez besoin d’un historique, faites s’abonner un consommateur qui écrit les messages dans une base de données.
Topics et contrôle d’accès
Les brokers autorisent les opérations de publication et d’abonnement topic par topic : votre hiérarchie sert donc aussi de modèle de permissions. Si chaque appareil n’écrit que sous acme/<site>/<type>/<device-id>/, vous pouvez lui accorder exactement ce sous-arbre et rien d’autre. Si les topics sont plats ou incohérents, écrire des règles strictes devient impossible et les équipes finissent par accorder # à tout le monde.
Essayez par vous-même
Ouvrez le client MQTT en ligne, abonnez-vous à testmqtt/demo/+/temperature et publiez sur testmqtt/demo/kitchen/temperature et testmqtt/demo/kitchen/oven/temperature. Seul le premier message arrive — exactement ce que prévoit la règle du +.
Essayez-le dans le client MQTT en ligne
Questions fréquentes
Quelle est la différence entre + et # en MQTT ?
Le joker + correspond à exactement un niveau de topic et peut apparaître n’importe où dans un filtre. Le joker # correspond à un nombre quelconque de niveaux, y compris zéro, et doit être le dernier caractère du filtre.
Peut-on publier sur un topic qui contient un joker ?
Non. Les jokers ne sont valides que dans les filtres d’abonnement. Un PUBLISH avec + ou # dans le nom de topic est une erreur de protocole, et le broker fermera la connexion.
S’abonner à # inclut-il les topics $SYS ?
Non. Les filtres qui commencent par un joker ne correspondent pas aux topics commençant par $. Pour recevoir les statistiques du broker, vous devez vous abonner explicitement, par exemple à $SYS/#.