Notions de base

Keep alive MQTT expliqué : PINGREQ, timeouts et réglages

Fonctionnement du keep alive MQTT : la règle du 1,5×, PINGREQ et PINGRESP, Server Keep Alive en MQTT 5, pièges NAT et mobiles, et choix d’un bon intervalle.

Mis à jour · 7 min de lecture

Les connexions TCP peuvent mourir en silence. Un routeur redémarre, un téléphone change de cellule, une entrée de table NAT expire — et aucune des deux parties ne reçoit de fermeture propre. Le mécanisme de keep alive de MQTT existe pour que le client comme le broker détectent une connexion morte dans un délai prévisible, et pour que le broker puisse alors publier le message Last Will du client. Cet article explique précisément le fonctionnement du keep alive en MQTT 3.1.1 et 5, et comment choisir une valeur adaptée à votre réseau.

Qu’est-ce que l’intervalle de keep alive

Le keep alive est une valeur sur 16 bits, exprimée en secondes, que le client envoie dans son paquet CONNECT. C’est une promesse : « je ne resterai jamais silencieux plus longtemps que cela ». La valeur maximale est de 65535 secondes (un peu plus de 18 heures), et 0 désactive complètement le mécanisme.

Point essentiel : le minuteur concerne n’importe quel paquet de contrôle, pas seulement les pings. Un client qui publie une mesure toutes les 10 secondes avec un keep alive de 60 secondes n’a jamais besoin d’envoyer de ping, car ses paquets PUBLISH prouvent déjà qu’il est vivant. Les pings ne sont envoyés que lorsque le client n’a rien d’autre à dire.

PINGREQ et PINGRESP

Lorsque la période de keep alive est sur le point de s’écouler sans que le client ait rien envoyé, il envoie un PINGREQ. Le broker doit répondre par un PINGRESP. Les deux paquets sont minuscules : un simple en-tête fixe de 2 octets, sans en-tête variable ni payload.

PaquetSensOctets sur le réseauRôle
PINGREQClient → broker0xC0 0x00Prouve que le client est vivant ; demande si le broker l’est aussi
PINGRESPBroker → client0xD0 0x00Prouve que le broker et le chemin retour vers le client fonctionnent

Deux octets de MQTT ne racontent pas toute l’histoire — TCP/IP, les enregistrements TLS et, pour les navigateurs, le framing WebSocket ajoutent tous un surcoût à chaque ping. Si vous dimensionnez un forfait de données cellulaires, le calculateur de taille de paquet MQTT vous aide à estimer la partie MQTT de chaque paquet, à laquelle vous ajouterez le surcoût de votre transport.

La règle du 1,5× : quand une connexion est déclarée morte

Les deux parties utilisent le keep alive différemment :

  • Côté broker — si le broker ne reçoit aucun paquet de contrôle du client pendant une fois et demie la période de keep alive, il doit fermer la connexion réseau comme si le réseau était tombé. Avec un keep alive de 60 secondes, cela représente 90 secondes de silence.
  • Côté client — si le client envoie un PINGREQ et ne reçoit pas de PINGRESP dans un délai raisonnable, il doit fermer lui-même la connexion. Les bibliothèques considèrent généralement l’absence de réponse au ping au tick de keep alive suivant comme un échec et lancent la reconnexion.

Comme le broker traite un dépassement du keep alive comme une déconnexion anormale, le Last Will du client est publié. C’est ce qui fait fonctionner le pattern classique « appareil hors ligne » : définissez un will retenu offline sur devices/42/status, et le broker annonce la panne à votre place au plus tard 1,5 période de keep alive après la disparition de l’appareil.

Server Keep Alive en MQTT 5

En MQTT 3.1.1, c’est le client qui choisit le keep alive et le broker doit l’accepter (ou refuser la connexion). MQTT 5 ajoute une propriété Server Keep Alive au CONNACK. Si le broker l’inclut, le client doit utiliser la valeur du broker au lieu de celle qu’il a demandée. Les brokers s’en servent pour empêcher les clients de demander un keep alive de 0 ou de plusieurs heures, ce qui laisserait s’accumuler les connexions mortes.

MQTT 5 rend aussi l’échec explicite : avant de fermer, un broker peut envoyer un DISCONNECT avec le reason code 0x8D (Keep Alive timeout). Vous pouvez consulter ce code, et tous les autres, dans la référence des reason codes MQTT. Voir MQTT 5 vs 3.1.1 pour les autres différences du protocole.

Les brokers imposent souvent aussi des limites côté serveur. Mosquitto, par exemple, dispose d’une option max_keepalive : les clients MQTT 5 reçoivent la valeur plafonnée via Server Keep Alive, tandis que les clients MQTT 3.1.1 qui demandent davantage peuvent être refusés.

Configurer le keep alive dans les clients courants

La plupart des bibliothèques utilisent 60 secondes par défaut. Voici comment le modifier :

mosquitto_sub
# -k sets the keep alive in seconds
mosquitto_sub -h broker.hivemq.com -t 'testmqtt/ka-demo/#' -k 30 -v
MQTT.js
import mqtt from 'mqtt';

const client = mqtt.connect('wss://broker.hivemq.com:8884/mqtt', {
  keepalive: 30,        // seconds; 0 disables
  reconnectPeriod: 2000 // ms between reconnect attempts
});
Paho MQTT (Python)
import paho.mqtt.client as mqtt

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.connect("broker.hivemq.com", 1883, keepalive=30)
client.loop_forever()

Vous voulez l’extrait complet pour votre langage ? Le générateur de code MQTT produit un code de connexion avec le keep alive déjà configuré. Pour observer le comportement en direct, connectez le client MQTT en ligne avec un keep alive court et laissez-le inactif.

Essayez-le dans le client MQTT en ligne

NAT, pare-feu et réseaux mobiles

Le keep alive a une seconde mission que la spécification ne mentionne pas : satisfaire les équipements intermédiaires. Les passerelles NAT, le CGNAT des réseaux mobiles, les load balancers et les pare-feu à état suppriment tous les flux TCP inactifs après un certain délai. Une fois l’entrée supprimée, le client se croit toujours connecté, mais rien de ce qu’il envoie n’atteint le broker, et rien de ce que le broker envoie n’atteint le client.

  • Restez sous le délai d’inactivité le plus court du chemin. Les load balancers cloud et les opérateurs mobiles utilisent souvent des délais de quelques minutes, parfois moins. Un keep alive nettement inférieur maintient l’entrée NAT active.
  • Ne comptez pas sur le keepalive TCP. Les valeurs par défaut du keepalive TCP des systèmes d’exploitation se comptent généralement en heures, bien trop lent pour protéger une session MQTT.
  • Trouvez l’équilibre avec la batterie. Chaque ping réveille la radio. Sur les appareils cellulaires sur batterie, des intervalles plus longs combinés à une session persistante (pour que les messages manqués soient mis en file) sont souvent le meilleur compromis.
  • Les WebSockets ne font pas exception. Les clients navigateur derrière des proxys subissent les mêmes délais d’inactivité ; le keep alive MQTT fonctionne de la même façon avec MQTT sur WebSockets.

Comment choisir une valeur de keep alive

ScénarioKeep alive suggéréPourquoi
Tableaux de bord et services backend sur réseaux stables30–60 sValeur par défaut des bibliothèques, faible surcoût, détection en une minute environ
Appareils dont le statut « offline » doit s’afficher vite10–20 sLe message will se déclenche en 15 à 30 s environ
Réseaux cellulaires / fortement NATésSous le délai d’inactivité le plus court du cheminÉvite les connexions semi-ouvertes silencieuses
Sur batterie, envois peu fréquentsPlusieurs minutes, ou connexion–publication–déconnexionMoins de réveils radio ; s’appuyer sur les sessions persistantes

Dépanner les déconnexions liées au keep alive

Si des clients se déconnectent toutes les 1,5× keep alive, la cause habituelle est une boucle cliente qui ne tourne pas — par exemple la boucle réseau de Paho bloquée par un traitement long dans un callback, si bien qu’aucun PINGREQ n’est envoyé. Des reconnexions fréquentes à intervalle fixe de quelques minutes désignent plutôt un délai d’inactivité sur un proxy ou un NAT. Pour les autres causes, consultez le guide des erreurs de connexion MQTT.

Questions fréquentes

Quel est un bon intervalle de keep alive MQTT ?

Pour la plupart des appareils sur des réseaux stables, 30 à 60 secondes est une valeur par défaut raisonnable. Utilisez des valeurs plus courtes (15 à 30 secondes) si vous devez détecter rapidement les clients morts ou rester sous un délai NAT agressif, et des valeurs plus longues sur les appareils sur batterie, où chaque réveil radio coûte de l’énergie.

Que se passe-t-il quand le keep alive MQTT expire ?

Si le broker ne reçoit aucun paquet de contrôle du client pendant une fois et demie l’intervalle de keep alive, il ferme la connexion réseau et la traite comme une déconnexion anormale. Le message Last Will, s’il existe, est donc publié. En MQTT 5, le broker peut d’abord envoyer un DISCONNECT avec le reason code 0x8D (Keep Alive timeout).

Mettre le keep alive à 0 le désactive-t-il ?

Oui. Un keep alive de 0 désactive le mécanisme : le broker ne déconnecte jamais le client pour inactivité. C’est rarement une bonne idée, car des connexions TCP semi-ouvertes peuvent alors subsister très longtemps sans que personne ne s’en aperçoive.