L'intervalle keep alive MQTT est le nombre de secondes pendant lesquelles un client promet de ne jamais rester silencieux, et c'est le principal outil dont dispose un broker pour repérer les connexions mortes. Dans ce guide, vous verrez précisément comment fonctionnent PINGREQ, PINGRESP et la règle du timeout à 1,5x, comment le keep alive interagit avec les routeurs NAT, les liens cellulaires et l'autonomie de la batterie, et quelles valeurs choisir pour démarrer avec vos appareils.
Ce que fait réellement l'intervalle keep alive MQTT
Lorsqu'un client envoie un CONNECT, il y inclut un champ Keep Alive de deux octets exprimé en secondes. Cette valeur est un contrat : « je vous enverrai un paquet de contrôle au moins une fois sur cette période ». N'importe quel paquet compte, qu'il s'agisse d'un PUBLISH, d'un SUBSCRIBE ou d'un PUBACK. Ce n'est que lorsque le client n'a rien d'autre à envoyer qu'il se rabat sur un minuscule paquet PINGREQ, auquel le broker répond par un PINGRESP.
Le keep alive existe parce que TCP lui-même détecte mal les pairs morts. Si un appareil perd son alimentation ou si son modem cellulaire décroche du réseau, aucun paquet FIN ou RST n'est jamais envoyé. Le socket du broker reste « ouvert » indéfiniment de son point de vue, et tout subscriber qui attend le Last Will and Testament de l'appareil attend lui aussi indéfiniment. Le keep alive donne une échéance aux deux côtés.
La règle du timeout à 1,5x
La spécification MQTT indique que si le broker ne reçoit rien d'un client pendant une fois et demie l'intervalle de keep alive, il doit fermer la connexion réseau comme si elle avait échoué. Cela signifie :
| Keep alive | Le broker abandonne après | Usage typique |
|---|---|---|
| 15 s | 22,5 s | Tableaux de bord interactifs, basculement rapide |
| 30 s | 45 s | Appareils sur secteur avec un Wi-Fi peu fiable |
| 60 s | 90 s | Valeur par défaut raisonnable pour la plupart des appareils |
| 120 s | 180 s | Appareils cellulaires attentifs à leur consommation de données |
| 300 s | 450 s | Passerelles peu bavardes sur des liens stables |
| 0 | Jamais | Keep alive désactivé (à éviter en production) |
Le client a sa propre part du contrat. S'il envoie un PINGREQ et ne reçoit pas de PINGRESP dans un « délai raisonnable » (la plupart des bibliothèques utilisent la valeur du keep alive ou un timeout fixe), il doit considérer la connexion comme rompue et se reconnecter. C'est ainsi qu'un client découvre un socket à moitié ouvert de son côté.
Ce qui se passe quand le timeout se déclenche
Lorsque le broker ferme une connexion à cause du keep alive, il la traite comme une déconnexion anormale. Conséquences pratiques :
- Le message will du client est publié (après le will delay, si vous en avez défini un en MQTT 5 ; consultez le will delay interval MQTT).
- Si le client avait une session persistante, le broker conserve ses abonnements et commence à mettre en file d'attente les messages QoS 1 et QoS 2 qui lui sont destinés.
- Les topics de statut en ligne et les tableaux de bord passent à « hors ligne ».
Le keep alive contrôle donc directement la rapidité avec laquelle votre système apprend qu'un problème est survenu.
Choisir une valeur de keep alive MQTT
Il n'existe pas de valeur universellement correcte. Vous arbitrez entre vitesse de détection d'une part, trafic et consommation d'énergie d'autre part.
Vitesse de détection
Un intervalle plus court permet au broker et aux subscribers d'apprendre plus vite les pannes. Si un tableau de bord d'exploitation doit afficher une machine hors ligne en moins d'une demi-minute, un keep alive de 60 secondes (détection à 90 secondes) ne répondra pas à cette exigence, alors que 15 ou 20 secondes conviendront.
Timeouts d'inactivité des NAT et pare-feu
C'est le piège dans lequel tombent la plupart des équipes. Les box domestiques, les pare-feu d'entreprise, les load balancers cloud et surtout les passerelles NAT des opérateurs mobiles suppriment les translations TCP restées inactives pendant un certain temps. Une fois la translation supprimée, le paquet suivant du client ne va nulle part, et le broker ne s'en aperçoit qu'à l'échéance des 1,5x. Si votre keep alive est plus long que le plus court timeout d'inactivité NAT sur le chemin, vous subissez des déconnexions mystérieuses toutes les quelques minutes. Les timeouts NAT des opérateurs varient beaucoup et ne sont pas toujours documentés : sur les liens cellulaires, il est donc plus sûr de rester nettement sous quelques minutes.
Batterie et consommation de données
Chaque aller-retour PINGREQ/PINGRESP ne représente que 2 octets de payload MQTT dans chaque sens, plus le surcoût TCP/IP (et des enregistrements TLS). En Wi-Fi, c'est négligeable. Sur un appareil cellulaire sur batterie, le coût tient surtout aux réveils de la radio, pas aux octets : chaque ping peut maintenir le modem dans un état de forte consommation pendant plusieurs secondes. Pour ces appareils, demandez-vous si une connexion permanente est vraiment nécessaire, ou s'il vaut mieux se réveiller, publier et se déconnecter avec une session persistante.
Un point de départ pratique
- Appareils sur secteur en Wi-Fi ou Ethernet : 60 secondes.
- Tableaux de bord et clients navigateur en WebSocket : 30 secondes.
- Passerelles cellulaires : 60 à 120 secondes, puis réduisez si vous constatez des coupures inexpliquées.
- Services backend dans la même région cloud : 30 à 60 secondes.
- N'utilisez jamais 0 en production : cela supprime totalement la détection des connexions mortes.
Définir l'intervalle keep alive dans les clients courants
Vous pouvez tester tous ces exemples sur le serveur MQTT public gratuit broker.connectmq.com, réservé aux tests et aux prototypes. Utilisez un client ID unique et un préfixe de topic unique, et n'oubliez pas que l'espace public est lisible par tous.
mosquitto_sub et mosquitto_pub
# S'abonner avec un keep alive de 30 secondes et la sortie de débogage pour voir PINGREQ/PINGRESP
mosquitto_sub -h broker.connectmq.com -p 1883 -i ka-demo-7f3a \
-k 30 -d -t 'connectmq/demo/7f3a/#'
Avec -d, vous verrez des lignes comme Client ka-demo-7f3a sending PINGREQ et received PINGRESP toutes les 30 secondes tant que le topic reste calme.
Python (paho-mqtt 2.x)
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, reason_code, properties):
print("Connected:", reason_code)
client.subscribe("connectmq/demo/7f3a/#", qos=1)
def on_disconnect(client, userdata, flags, reason_code, properties):
print("Disconnected:", reason_code)
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id="ka-python-7f3a",
protocol=mqtt.MQTTv5,
)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
# keepalive est le troisième argument, en secondes
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_forever()
paho envoie automatiquement les PINGREQ depuis sa boucle réseau. Si vous bloquez la boucle (par exemple avec un long time.sleep dans un callback), les pings s'arrêtent et le broker vous déconnectera après 1,5x l'intervalle.
Node.js (MQTT.js v5)
const mqtt = require("mqtt");
const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
clientId: "ka-node-7f3a",
protocolVersion: 5,
keepalive: 45, // secondes
reconnectPeriod: 5000, // ms entre les tentatives de reconnexion
});
client.on("connect", () => console.log("connected"));
client.on("close", () => console.log("connection closed"));
client.on("error", (err) => console.error(err.message));
ESP32 (PubSubClient)
PubSubClient utilise 15 secondes par défaut. Modifiez la valeur avant d'appeler connect() avec client.setKeepAlive(60);, et veillez à ce que client.loop() s'exécute fréquemment dans votre sketch, car les pings ne sont envoyés que depuis loop(). Les longs appels à delay() sont la raison la plus fréquente pour laquelle les cartes ESP32 décrochent à intervalles réguliers. Un sketch ESP32 bien structuré utilise une boucle non bloquante avec des minuteries millis() pour l'éviter.
Server Keep Alive en MQTT 5
MQTT 5 permet au broker de passer outre la demande du client. Si le CONNACK contient une propriété Server Keep Alive, le client doit utiliser cette valeur au lieu de la sienne. Les brokers le font pour imposer un intervalle minimum ou maximum sur une plateforme partagée. La plupart des bibliothèques l'appliquent silencieusement : si vous constatez des pings à un rythme différent de celui que vous avez configuré, journalisez les propriétés du CONNACK. Dans paho, vous pouvez afficher properties dans on_connect ; MQTT.js les expose sur le paquet connack transmis à l'événement connect.
Dépanner les problèmes de keep alive
Utilisez cette check-list lorsque des clients se déconnectent à des intervalles étrangement réguliers :
- Mesurez l'écart. Si les déconnexions surviennent environ 1,5x votre keep alive après la dernière activité, le client n'envoie pas de pings. Cherchez une boucle réseau bloquée.
- Recherchez une coupure d'inactivité fixe. Si les coupures surviennent après un nombre constant de minutes quel que soit le keep alive, un NAT ou un pare-feu arrive en timeout. Abaissez l'intervalle sous cette valeur.
- Recherchez des client ID en double. Deux clients avec le même ID s'éjectent mutuellement, ce qui ressemble à un problème de keep alive sans en être un. Consultez les bonnes pratiques pour le client ID MQTT.
- Méfiez-vous des callbacks monothread. Un traitement lourd dans
on_messageretarde le PINGREQ. Déplacez le traitement vers un thread de travail ou une file d'attente. - Vérifiez que les poignées de main TLS aboutissent. Sur les appareils contraints, une reconnexion TLS lente peut repousser le ping suivant au-delà de l'échéance.
- Activez la journalisation de débogage de votre bibliothèque et comparez les horodatages du client avec les événements de connexion du broker.
Sur un broker ConnectMQ, vous pouvez aussi surveiller $SYS/broker/connection/{clientId}/state pour voir précisément quand le broker considère un client comme connecté ou déconnecté, ce qui facilite la corrélation avec les journaux de vos appareils. Le client MQTT intégré au navigateur du portail permet de s'abonner rapidement à ce topic sans rien installer.
Keep alive, sessions et Last Will travaillent ensemble
Le keep alive n'est qu'une pièce d'une conception plus large de la fiabilité. Un modèle de production raisonnable ressemble à ceci :
- Un keep alive assez court pour devancer les timeouts NAT et atteindre votre objectif de détection.
- Un message « online » retenu publié à la connexion, plus un message will « offline » retenu.
- Une session persistante pour que les messages QoS 1 publiés pendant la reconnexion de l'appareil ne soient pas perdus.
- Un backoff exponentiel à la reconnexion, pour qu'un redémarrage du broker ne se transforme pas en ruée simultanée.
Le tutoriel MQTT couvre ces briques depuis le début si vous souhaitez le contexte plus large.
Démarrer avec ConnectMQ
ConnectMQ est un broker MQTT managé qui prend en charge MQTT 3.1.1 et 5.0 en TCP, TLS, WebSocket et WebSocket sécurisé : vous pouvez donc tester n'importe quelle stratégie de keep alive sur les mêmes endpoints que ceux que vous utiliserez en production. Lorsque vous êtes prêt à dépasser le serveur MQTT public gratuit, créez un broker Serverless gratuit sans carte bancaire, copiez les identifiants générés et suivez l'état des connexions en direct dans le portail. Si vous comparez encore les options, notre guide pour choisir un broker MQTT cloud passe en revue les compromis.
Questions fréquentes
Quel est un bon intervalle keep alive MQTT par défaut ?
60 secondes est une bonne valeur par défaut pour la plupart des appareils sur secteur. Réduisez-la à 15 à 30 secondes si vous avez besoin d'une détection hors ligne plus rapide, ou si un équipement NAT sur le chemin coupe plus tôt les connexions inactives.
N'importe quel paquet MQTT réinitialise-t-il le minuteur keep alive ?
Oui. Tout paquet de contrôle envoyé par le client, y compris PUBLISH et PUBACK, compte comme une activité. Le PINGREQ n'est envoyé que lorsque le client est resté inactif pendant tout l'intervalle.
Que se passe-t-il si je règle le keep alive sur 0 ?
Le keep alive est désactivé : le broker ne ferme donc jamais de lui-même une connexion silencieuse. Des appareils morts peuvent sembler connectés indéfiniment et leurs messages will ne jamais être envoyés : évitez 0 en production.
Pourquoi mon client se déconnecte-t-il exactement toutes les quelques minutes ?
Un intervalle constant quel que soit votre réglage de keep alive indique généralement un timeout d'inactivité NAT ou pare-feu. Réglez le keep alive sous ce timeout pour que les pings maintiennent la translation active.
Le broker peut-il modifier ma valeur de keep alive ?
En MQTT 5, oui. Le broker peut renvoyer une propriété Server Keep Alive dans le CONNACK, et le client doit utiliser cette valeur au lieu de celle qu'il a demandée.



