Fondamentaux MQTT

Session persistante MQTT et flag Clean Session expliqués

Une session persistante permet au broker de mémoriser les abonnements d'un client et de mettre en file ses messages QoS 1 et 2 pendant qu'il est hors ligne. Découvrez ce qui est stocké, quand l'utiliser et les pièges à éviter.

Schéma d'une session persistante MQTT montrant un broker qui conserve les abonnements et les messages en file d'attente pour un appareil IoT déconnecté
Essayez-le sur votre propre broker MQTTObtenez un broker MQTT privé et managé avec l’offre Free et partez d’exemples de code prêts à l’emploi.
Essayer gratuitement Exemples de code Aucune carte bancaire requise

Une session persistante MQTT permet au broker de se souvenir de l'identité d'un client, de ses abonnements et des messages qu'il lui doit encore, même lorsque le client est déconnecté. À la fin de cet article, vous saurez exactement ce que le broker stocke, comment le flag clean session (et son remplaçant dans MQTT 5) le contrôle, et comment vérifier ce comportement vous-même en quelques commandes.

Qu'est-ce qu'une session persistante MQTT ?

Chaque connexion MQTT possède une session : un ensemble d'états partagés entre le client et le broker MQTT. Avec une session propre (non persistante), cet état ne vit que le temps de la connexion réseau. À la déconnexion, le broker efface tout. Avec une session persistante, le broker conserve l'état après la fermeture de la connexion et le restitue lorsque le même client se reconnecte.

L'identité qui relie l'ancienne session à la nouvelle connexion est le client ID. C'est pourquoi les sessions persistantes ne fonctionnent que si le client se reconnecte à chaque fois avec exactement le même identifiant.

Ce que le broker stocke

État de session sur le broker Stocké avec une session persistante ?
Les abonnements du client (filtres de topic et QoS) Oui
Les messages QoS 1 et QoS 2 arrivés pendant que le client était hors ligne Oui
Les messages QoS 1 et QoS 2 envoyés mais pas encore acquittés Oui
Les messages QoS 2 reçus du client mais dont l'échange n'est pas terminé Oui
Les messages QoS 0 publiés pendant que le client était hors ligne Non (les brokers peuvent les mettre en file en option, la plupart ne le font pas)
Retained messages Ne font pas partie de l'état de session ; stockés par topic pour tout le monde

Le client conserve sa propre moitié : les messages QoS 1 et 2 qu'il a envoyés mais qui ne sont pas encore acquittés, et les messages QoS 2 qu'il a reçus mais pas encore finalisés. Une bibliothèque cliente qui garde ces données uniquement en mémoire perd sa moitié au redémarrage, ce qui est une source fréquente de confusion.

Ce qu'elle ne fait pas

Une session persistante n'est pas une base de données. Elle ne stocke pas d'historique, ne rejoue pas les messages déjà acquittés par le client et ne garantit pas la livraison du trafic QoS 0. Elle ne conserve par ailleurs que les messages des topics auxquels le client était déjà abonné avant de passer hors ligne. Si vous avez besoin de la « dernière valeur » d'un topic indépendamment des sessions, utilisez plutôt les retained messages.

Le flag Clean Session dans MQTT 3.1.1

Dans MQTT 3.1.1, un seul bit du paquet CONNECT contrôle tout :

  • cleanSession = true : supprime toute session existante, repart de zéro et supprime cette session lorsque le client se déconnecte.
  • cleanSession = false : reprend la session existante pour ce client ID s'il y en a une, sinon en crée une, et la conserve après la déconnexion.

Le broker indique au client ce qui s'est passé via le flag Session Present du CONNACK. Si vous vous êtes connecté avec cleanSession = false et que Session Present vaut 0, le broker n'avait aucun état pour vous : vous devez vous réabonner. S'il vaut 1, vos abonnements sont toujours en place et les messages en file d'attente vont arriver.

La faiblesse de 3.1.1 est qu'une session persistante n'a pas d'expiration intégrée. Un appareil mis hors service laisse derrière lui une session qui continue d'accumuler des messages jusqu'à ce que les limites propres au broker entrent en jeu.

Les sessions persistantes dans MQTT 5

MQTT 5 scinde ce flag en deux contrôles indépendants :

  • Clean Start détermine s'il faut supprimer une session existante au moment de la connexion.
  • Session Expiry Interval détermine combien de temps, en secondes, la session survit après la déconnexion.

Une session persistante en MQTT 5 correspond donc à Clean Start = false associé à un Session Expiry Interval supérieur à zéro. La correspondance complète, et la manière de choisir les valeurs, sont détaillées dans Clean Start et Session Expiry Interval dans MQTT 5. Les brokers peuvent plafonner l'expiration demandée ; sur le serveur MQTT public gratuit broker.connectmq.com, le maximum est de 30 minutes.

Tester une session persistante MQTT pas à pas

Cette expérience utilise le serveur MQTT public gratuit. Choisissez votre propre suffixe aléatoire à la place de p9k2 pour ne pas entrer en collision avec d'autres lecteurs, et n'envoyez pas de données sensibles, car l'espace public est lisible par tous.

  1. Lancez un abonné avec un ID fixe, une session persistante et la QoS 1 :
mosquitto_sub -h broker.connectmq.com -p 1883 -V mqttv5 \
  -i persist-demo-p9k2 -c -x 1800 -q 1 -v \
  -t 'connectmq/demo/p9k2/alerts'

-c désactive clean start et -x 1800 demande une expiration de session de 30 minutes.

  1. Arrêtez l'abonné avec Ctrl+C.

  2. Publiez trois messages QoS 1 pendant qu'il est hors ligne :

for i in 1 2 3; do
  mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-demo-p9k2 \
    -q 1 -t 'connectmq/demo/p9k2/alerts' -m "alert $i"
done
  1. Relancez exactement la même commande d'abonnement. Les trois messages arrivent immédiatement, car le broker les a mis en file dans votre session.

  2. Refaites le test sans -c. Cette fois, rien n'arrive à la reconnexion : la session a été nettoyée.

Le même test en Python

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

TOPIC = "connectmq/demo/p9k2/alerts"

def on_connect(client, userdata, flags, reason_code, properties):
    print("Connected:", reason_code, "session present:", flags.session_present)
    if not flags.session_present:
        # Le broker n'a pas de session pour nous : on se réabonne
        client.subscribe(TOPIC, qos=1)

def on_message(client, userdata, msg):
    print(msg.topic, msg.payload.decode())

client = mqtt.Client(
    mqtt.CallbackAPIVersion.VERSION2,
    client_id="persist-py-p9k2",
    protocol=mqtt.MQTTv5,
)
client.on_connect = on_connect
client.on_message = on_message

props = Properties(PacketTypes.CONNECT)
props.SessionExpiryInterval = 1800  # secondes

client.connect("broker.connectmq.com", 1883, keepalive=60,
               clean_start=False, properties=props)
client.loop_forever()

Vérifier session_present avant de s'abonner est le modèle idiomatique : cela évite les réabonnements inutiles et permet de se rétablir correctement lorsque la session a expiré.

Quand utiliser une session persistante

Utilisez-en une lorsque la perte d'un message a des conséquences et que le client se reconnecte avec une identité stable :

  • Les appareils qui reçoivent des commandes (ouvrir une vanne, mettre à jour une configuration) et peuvent brièvement quitter le réseau.
  • Les consommateurs backend qui doivent traiter chaque événement QoS 1, comme les gestionnaires d'alarmes.
  • Les appareils sur batterie qui se réveillent, se connectent, récupèrent les commandes en attente puis se rendorment.

Préférez une session propre lorsque :

  • Le client ne s'intéresse qu'aux données en direct, comme un tableau de bord qui affiche les valeurs courantes issues de topics retenus.
  • Les client ID sont aléatoires ou réutilisés entre plusieurs instances, comme des workers web mis à l'échelle automatiquement.
  • Vous ne faites que publier, sans jamais vous abonner ; il y a alors peu d'état de session à conserver.

Pièges et dépannage

  1. Client ID aléatoires. De nombreuses bibliothèques génèrent un ID aléatoire si vous le laissez vide. Un nouvel ID signifie une nouvelle session à chaque fois : rien n'est jamais repris. Définissez un ID fixe ; consultez les bonnes pratiques pour le client ID MQTT.
  2. S'abonner en QoS 0. Le broker ne met en file que les messages au niveau de QoS de l'abonnement. Un abonnement QoS 0 ne reçoit rien hors ligne, même si l'éditeur a utilisé la QoS 1.
  3. Publier en QoS 0. La livraison utilise le plus faible des deux niveaux de QoS (publication et abonnement). Les publications QoS 0 ne sont pas mises en file.
  4. S'attendre à recevoir des messages antérieurs au premier abonnement. Une session ne met en file que les messages correspondant aux abonnements qu'elle possède déjà.
  5. Avalanche de messages à la reconnexion. Un appareil hors ligne pendant des heures peut recevoir une rafale de messages en attente. Dimensionnez vos tampons, ou utilisez l'expiration des messages de MQTT 5 pour que les commandes obsolètes disparaissent de la file.
  6. Redémarrages du broker. Le stockage des sessions est un détail d'implémentation propre à chaque broker. Sur ConnectMQ, les sessions sont conservées en mémoire : elles survivent aux déconnexions des clients, mais pas à un redémarrage du broker. Concevez en conséquence : vérifiez Session Present et réabonnez-vous lorsqu'il vaut 0, et utilisez des retained messages pour l'état qui doit toujours être disponible.
  7. Limites des offres. L'offre ConnectMQ Serverless (Free) prend en charge la QoS jusqu'au niveau 1, ce qui suffit pour la livraison en file d'attente. La QoS 2 est disponible sur les offres payantes.

Pour examiner de plus près ce qui est mis en file et en quelle quantité, lisez comment MQTT met en file les messages des clients hors ligne. Vous découvrez le protocole ? Le tutoriel MQTT part des bases.

Utiliser les sessions persistantes sur ConnectMQ

ConnectMQ est un broker MQTT managé compatible MQTT 3.1.1 et 5.0 : le flag clean session comme l'expiration de session de MQTT 5 fonctionnent donc immédiatement. Chaque broker est fourni avec des identifiants générés, et les client ID sont liés à ces identifiants, ce qui empêche un inconnu de détourner la session de votre appareil. Inscrivez-vous à l'offre Serverless gratuite sans carte bancaire, connectez-vous avec YOUR_USERNAME, YOUR_PASSWORD et YOUR_CLIENT_ID, puis refaites le test ci-dessus sur votre propre broker privé.

Questions fréquentes

Une session persistante MQTT stocke-t-elle les messages QoS 0 ?

En général, non. La spécification n'impose la mise en file que des messages QoS 1 et QoS 2 ; le stockage des messages QoS 0 est facultatif, et la plupart des brokers ne le font pas. Utilisez la QoS 1 pour tout ce que vous ne pouvez pas vous permettre de perdre.

Pourquoi ne reçois-je pas les messages en attente après m'être reconnecté ?

Les causes les plus courantes sont un client ID modifié, une connexion avec clean session ou clean start à true, un abonnement en QoS 0 ou une session déjà expirée. Vérifiez le flag Session Present du CONNACK pour savoir si la session a été reprise.

Dois-je me réabonner avec une session persistante ?

Uniquement si Session Present vaut 0. Lorsque le broker reprend votre session, vos abonnements existent déjà et vous pouvez vous dispenser de vous abonner.

Les sessions persistantes survivent-elles à un redémarrage du broker ?

Cela dépend du broker. ConnectMQ conserve les sessions en mémoire : elles survivent aux déconnexions des clients mais sont effacées si le broker redémarre ; les clients doivent donc gérer proprement le cas Session Present = 0.

Articles liés

Qui a inventé MQTT ? L'histoire, des oléoducs à l'IoT

MQTT a été inventé en 1999 par Andy Stanford-Clark (IBM) et Arlen Nipper (Arcom) pour surveiller des oléoducs par satellite. Suivez son parcours vers l'open source, OASIS, l'ISO et les brokers MQTT managés d'aujourd'hui.

8 min de lecture

Pourquoi votre client MQTT se déconnecte sans cesse (et comment y remédier)

Les boucles de reconnexion sont l'un des problèmes MQTT les plus courants. Découvrez les cinq causes habituelles, des client ID en double aux timeouts de keep alive et aux paquets trop volumineux, et suivez une méthode de diagnostic qui identifie la vôtre.

9 min de lecture

Taille maximale d'un message MQTT : limites et stratégies pour les gros payloads

MQTT peut techniquement transporter un paquet de 256 Mo, mais les brokers, les bibliothèques clientes et les appareils imposent des limites bien plus basses. Découvrez où se trouvent les vraies limites, ce qui se passe quand on les dépasse et comment envoyer de gros payloads.

8 min de lecture

Tous les articles →

Votre broker MQTT privé, à quelques clics

Créez un compte, récupérez les identifiants de votre broker et connectez votre premier appareil — aucun serveur à installer, mettre à jour ou dimensionner.