La latence MQTT est le temps qui s'écoule entre l'envoi d'un message par un éditeur et sa réception par un abonné ; dans la plupart des systèmes IoT, elle est dominée par des facteurs extérieurs au protocole lui-même. Ce guide décompose chaque élément du temps aller-retour, explique quels réglages comptent vraiment et vous fournit un petit script Python pour mesurer la latence depuis votre propre réseau face à un broker réel.
Ce que « latence » signifie en MQTT
Le mot désigne plusieurs mesures différentes ; soyez donc précis avant d'optimiser :
- Latence aller simple : de l'éditeur à l'abonné. Difficile à mesurer avec exactitude, car les deux horloges se trouvent sur des machines différentes.
- Temps aller-retour (RTT) : un client publie sur un topic auquel il est lui-même abonné et mesure le temps nécessaire au retour du message. Une seule horloge : le chiffre est fiable. C'est ce que mesure le script ci-dessous.
- Latence de connexion : le temps entre l'ouverture d'un socket et la réception du CONNACK. Pertinente pour les appareils qui se réveillent, se connectent, publient puis se rendorment.
- Latence d'acquittement : le temps entre le PUBLISH et le PUBACK en QoS 1, qui vous indique à quel moment le broker a pris la responsabilité du message.
Pour les appareils qui maintiennent une connexion ouverte (le schéma MQTT normal), le temps aller-retour est l'indicateur unique le plus utile.
Les composantes de la latence MQTT
Un message qui va d'un capteur à un tableau de bord traverse plusieurs étapes, et chacune ajoute du délai :
| Étape | Ce qui se passe | Influence typique | Principal levier |
|---|---|---|---|
| Pile cliente | La bibliothèque met en file, sérialise, écrit sur le socket | Faible, mais importante sur des microcontrôleurs chargés | Boucle non bloquante, éviter les longs appels delay() |
| Dernier kilomètre | Accès Wi-Fi, cellulaire, satellite | Souvent la part la plus importante et la plus variable | Meilleure liaison, meilleur signal cellulaire, passerelle filaire |
| Chemin Internet | Routage vers la région du broker | Augmente avec la distance physique | Région du broker proche des appareils |
| TLS | Chiffrement par paquet, handshake à chaque connexion | Le handshake coûte des allers-retours une seule fois ; le coût par paquet est faible | Garder des connexions de longue durée |
| Handshake QoS | PUBACK ou flux QoS 2 en 4 étapes | Retarde peu la livraison, mais limite le débit | Choisir la QoS selon le type de données |
| Traitement par le broker | Authentification, correspondance des topics, diffusion | Généralement faible sur un broker en bonne santé | Éviter les diffusions massives et les topics surchargés |
| Côté abonné | Même chemin en sens inverse, plus le traitement applicatif | Symétrique du côté éditeur | Callbacks légers |
Distance réseau
La lumière dans la fibre est rapide, mais pas instantanée, et les routes réelles ne sont pas des lignes droites. Un appareil à Istanbul qui dialogue avec un broker sur un autre continent verra toujours une latence de base plus élevée qu'un appareil qui dialogue avec un broker de sa propre région. Aucun réglage du protocole ne peut l'éliminer ; seul l'emplacement du broker le peut.
Surcoût de TLS
Le handshake TLS ajoute des allers-retours à l'ouverture de la connexion. Ensuite, le chiffrement symétrique coûte très peu sur les processeurs modernes et reste modeste sur des puces comme l'ESP32. Comme les clients MQTT restent normalement connectés pendant des heures ou des jours, TLS affecte surtout la latence de connexion, et non la latence des messages en régime établi. C'est pourquoi « TLS est lent » est rarement une bonne raison d'utiliser le port 1883 ; consultez les ports MQTT expliqués pour les compromis.
Niveau de QoS
C'est l'aspect le plus mal compris. En QoS 0, le broker transmet immédiatement. En QoS 1, le broker transmet lui aussi immédiatement à la réception, et le PUBACK revient en parallèle : la latence de livraison est donc proche de celle de la QoS 0 sur une liaison saine. La QoS 2 ajoute un handshake en quatre étapes ; selon l'implémentation du broker, la transmission peut intervenir après la première ou la deuxième étape. L'effet le plus important d'une QoS élevée porte sur le débit et sur ce qui se passe en cas de perte de paquets : les retransmissions ajoutent de la latence lorsque le réseau se comporte mal. Le guide des niveaux de QoS MQTT détaille ces flux.
Nagle, mise en tampon et boucle cliente
Certaines piles retardent les petites écritures pour les regrouper. De nombreuses bibliothèques MQTT désactivent l'algorithme de Nagle, mais ce n'est pas toujours le cas des piles embarquées et des sockets personnalisés. Sur microcontrôleur, une boucle principale qui n'appelle client.loop() qu'une fois par seconde ajoute jusqu'à une seconde de latence aux messages entrants, quelle que soit la rapidité du réseau.
Keep-alive et reconnexions
Le keep-alive n'affecte pas la latence sur une connexion saine, mais il détermine la vitesse à laquelle une connexion morte est détectée. Une liaison coupée silencieusement avec un keep-alive de 300 secondes peut signifier plusieurs minutes avant que le client ne se reconnecte, et chaque message de cette fenêtre arrive en retard.
Mesurez vous-même la latence MQTT
Le script ci-dessous se connecte au serveur MQTT public gratuit broker.connectmq.com, réservé aux tests et aux prototypes, s'abonne à un topic unique, y publie des messages horodatés et calcule des statistiques d'aller-retour. Il reste sous la limite du serveur MQTT public gratuit de 10 messages par seconde et par client en envoyant deux messages par seconde.
# mqtt_rtt.py - mesurer la latence aller-retour MQTT
# pip install "paho-mqtt>=2.0"
import json
import statistics
import sys
import threading
import time
import uuid
import paho.mqtt.client as mqtt
HOST = "broker.connectmq.com"
USE_TLS = "--tls" in sys.argv
PORT = 8883 if USE_TLS else 1883
QOS = 1
SAMPLES = 50
INTERVAL = 0.5 # secondes entre deux publications (2 msg/s)
run_id = uuid.uuid4().hex[:8]
topic = f"connectmq/demo/{run_id}/rtt"
rtts = []
subscribed = threading.Event()
done = threading.Event()
def on_connect(client, userdata, flags, reason_code, properties):
print(f"Connected to {HOST}:{PORT} -> {reason_code}")
client.subscribe(topic, qos=QOS)
def on_subscribe(client, userdata, mid, reason_code_list, properties):
subscribed.set()
def on_message(client, userdata, msg):
received = time.perf_counter()
data = json.loads(msg.payload)
rtts.append((received - data["t"]) * 1000.0)
if len(rtts) >= SAMPLES:
done.set()
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"rtt-{run_id}")
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message
if USE_TLS:
client.tls_set() # utilise le magasin de CA du système
t0 = time.perf_counter()
client.connect(HOST, PORT, keepalive=60)
client.loop_start()
if not subscribed.wait(10):
sys.exit("Subscribe timed out")
print(f"Connect + subscribe took {(time.perf_counter() - t0) * 1000:.1f} ms")
for seq in range(SAMPLES):
payload = json.dumps({"seq": seq, "t": time.perf_counter()})
client.publish(topic, payload, qos=QOS)
time.sleep(INTERVAL)
done.wait(10)
client.loop_stop()
client.disconnect()
if not rtts:
sys.exit("No messages received")
rtts.sort()
p95 = rtts[int(len(rtts) * 0.95) - 1]
print(f"samples={len(rtts)} lost={SAMPLES - len(rtts)}")
print(f"min={rtts[0]:.1f} ms median={statistics.median(rtts):.1f} ms "
f"p95={p95:.1f} ms max={rtts[-1]:.1f} ms")
Exécutez-le deux fois et comparez :
python mqtt_rtt.py # TCP simple sur 1883
python mqtt_rtt.py --tls # TLS sur 8883
Interpréter les résultats
- Le minimum approche le meilleur cas : réseau plus broker, sans aucun obstacle. C'est votre plancher.
- La médiane correspond à ce que les utilisateurs vivent habituellement.
- Le p95 et le maximum révèlent la gigue due aux réémissions Wi-Fi, à l'ordonnancement cellulaire ou aux liaisons congestionnées. Pour les boucles de régulation et les alarmes, ils comptent davantage que la médiane.
- Connect + subscribe montre le coût du handshake TLS. Attendez-vous à une valeur nettement plus élevée avec
--tls, tandis que la médiane par message reste proche de celle de l'exécution en TCP simple. - Les échantillons perdus en QoS 1 signifient généralement que le script s'est terminé avant l'arrivée des messages tardifs, ou que la connexion a été coupée. Vérifiez la console pour repérer les déconnexions.
Lancez le test depuis l'endroit où vivent réellement vos appareils (réseau de l'usine, modem cellulaire, box domestique), et pas seulement depuis votre bureau. La différence constitue souvent l'enseignement le plus précieux.
Moyens concrets de réduire la latence MQTT
- Gardez les connexions ouvertes. Connectez-vous une fois, publiez de nombreuses fois. Se reconnecter à chaque message fait payer à chaque fois les handshakes TCP et TLS.
- Choisissez une région de broker proche de vos appareils. La distance fixe le plancher.
- Choisissez la QoS selon le type de données. La télémétrie à haute fréquence, où l'échantillon suivant remplace le précédent, peut utiliser la QoS 0 ; les commandes et les alarmes méritent la QoS 1.
- Gardez des payloads compacts. Les gros documents JSON mettent plus de temps à transiter sur les liaisons lentes. Envisagez des encodages binaires pour les données à haute fréquence et les topic aliases de MQTT 5 pour raccourcir les noms de topics répétés.
- Servez souvent la boucle cliente. Sur Arduino ou ESP32, appelez
loop()à chaque itération et évitez les délais bloquants. - Ajustez le keep-alive pour détecter rapidement les liaisons mortes (30 à 60 secondes est courant) sans gaspiller de bande passante.
- Évitez les sauts inutiles. Chaque bridge, passerelle ou relais Node-RED sur le chemin ajoute son propre traitement et sa propre file d'attente.
- Rendez les callbacks des abonnés rapides. Confiez les traitements lourds à un thread de travail ou à une file pour ne pas bloquer la boucle réseau.
Dépanner une latence élevée ou irrégulière
| Symptôme | Cause probable | À vérifier |
|---|---|---|
| RTT minimum élevé | Distance au broker ou réseau d'accès lent | Ping et traceroute vers l'hôte du broker |
| Bonne médiane, p95 catastrophique | Réémissions Wi-Fi, ordonnancement cellulaire | Tester sur une liaison filaire pour comparer |
| Latence qui augmente avec le temps | L'abonné ne suit pas, les messages s'accumulent | Durée des callbacks et nombre de messages en vol |
| Trous périodiques de plusieurs secondes | Code bloquant dans la boucle cliente | Longs sleep ou E/S synchrones dans les callbacks |
| Pics uniquement à la reconnexion | Handshake TLS plus reprise de session | Stabilité de la connexion et keep-alive |
| Limitation sur le serveur MQTT public gratuit | Limite de 10 msg/s par client | Réduire le débit de publication ou utiliser un broker privé |
De la mesure à la production
Le serveur MQTT public gratuit est partagé : considérez ses chiffres comme indicatifs de votre chemin réseau plutôt que comme un benchmark. Pour le trafic de production, un broker MQTT managé comme ConnectMQ vous offre un point d'accès privé et authentifié sur les ports 8883 et 8084, sans les limites de débit du serveur public ; le détail des plans figure dans le guide du broker MQTT cloud. Pour répéter le test sur votre propre broker ConnectMQ, ajoutez client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD"), définissez le client ID sur YOUR_CLIENT_ID et lancez le script avec --tls. Pour un contexte plus large sur le protocole, consultez le tutoriel MQTT et le fonctionnement de MQTT.
Démarrez avec ConnectMQ
Créez un broker Serverless gratuit sur app.connectmq.com, sans carte bancaire, et pointez le script de latence vers lui en deux lignes. Le client intégré au navigateur et l'explorateur de topics en direct de ConnectMQ vous aident à voir précisément quand chaque message arrive.
Questions fréquentes
Qu'est-ce qu'une bonne latence MQTT ?
Cela dépend de la distance et du réseau d'accès. Comparez votre RTT minimum avec un simple ping réseau vers l'hôte du broker ; si MQTT n'ajoute que peu de chose par-dessus, le broker n'est pas votre goulot d'étranglement.
La QoS 1 rend-elle MQTT plus lent que la QoS 0 ?
Sur une liaison saine, la latence de livraison est similaire, car le broker transmet le message avant la fin du PUBACK. La QoS 1 ajoute surtout du surcoût lorsque des paquets sont perdus et doivent être renvoyés.
TLS augmente-t-il la latence MQTT ?
TLS ajoute un temps de handshake à la connexion, mais sur une connexion de longue durée, le surcoût par message est faible. Garder les connexions ouvertes est le meilleur moyen d'en minimiser l'impact.
Pourquoi mesurer l'aller-retour plutôt que la latence aller simple ?
L'aller-retour utilise une seule horloge, ce qui évite les erreurs dues à des horloges non synchronisées sur les machines de l'éditeur et de l'abonné.



