La QoS maximum MQTT est l'aspect de la qualité de service qui surprend le plus : vous pouvez publier en QoS 2 et recevoir malgré tout un message en QoS 0. Le niveau réellement utilisé pour une livraison dépend du publisher, du subscriber et des limites propres au broker. Dans cet article, vous verrez comment se calcule la QoS effective, comment les brokers annoncent et appliquent un maximum, et comment tester précisément ce qu'obtient votre connexion.
La QoS se négocie à chaque saut
MQTT propose trois niveaux de QoS : 0 (au plus une fois), 1 (au moins une fois) et 2 (exactement une fois). S'ils sont nouveaux pour vous, commencez par les niveaux de QoS MQTT expliqués.
Le point essentiel est que la QoS n'est pas de bout en bout. Un message parcourt deux sauts distincts :
- Du publisher au broker, à la QoS choisie par le publisher pour ce PUBLISH.
- Du broker à chaque subscriber, à une QoS que le broker calcule pour cet abonnement.
Chaque saut a sa propre poignée de main. Le PUBACK du publisher vient du broker, pas du subscriber : un publisher ne sait donc jamais si un subscriber a reçu le message.
Comment se calcule la QoS effective
Pour chaque subscriber, le broker livre à la plus basse de deux valeurs : la QoS du PUBLISH entrant et la QoS accordée à l'abonnement correspondant.
| QoS de publication | QoS d'abonnement | QoS livrée |
|---|---|---|
| 0 | 2 | 0 |
| 1 | 0 | 0 |
| 1 | 2 | 1 |
| 2 | 1 | 1 |
| 2 | 2 | 2 |
Deux conséquences comptent en pratique :
- S'abonner en QoS 2 n'améliore rien. Si un capteur publie en QoS 0, chaque subscriber reçoit en QoS 0, quoi qu'il ait demandé.
- Un subscriber peut rétrograder volontairement. Un tableau de bord qui ne s'intéresse qu'à la dernière valeur peut s'abonner en QoS 0 à une télémétrie publiée en QoS 1, ce qui économise les acquittements sur son propre lien.
Si un filtre d'abonnement en chevauche un autre (par exemple plant/# et plant/line1/+), le broker peut livrer le message une seule fois à la QoS correspondante la plus élevée, ou une fois par abonnement en MQTT 5, selon l'implémentation. Évitez autant que possible les abonnements qui se chevauchent avec des QoS différentes.
Comment les brokers plafonnent la QoS
Un broker n'est pas obligé de prendre en charge tous les niveaux pour tous les clients. Il dispose de deux mécanismes pour l'indiquer.
QoS accordée dans le SUBACK. Lorsqu'un client s'abonne, le broker répond par un SUBACK contenant la QoS accordée pour chaque filtre. Il peut accorder un niveau inférieur à celui demandé. En MQTT 3.1.1, les codes de retour sont 0, 1, 2 ou 0x80 en cas d'échec ; en MQTT 5, ce sont des reason codes où 0x00, 0x01 et 0x02 signifient QoS accordée 0, 1 et 2. Un client bien écrit vérifie cette valeur au lieu de supposer que sa demande a été honorée.
Maximum QoS dans le CONNACK (MQTT 5). Un broker MQTT 5 qui ne prend pas en charge la QoS 2, ou les QoS 1 et 2, inclut une propriété Maximum QoS dans le CONNACK. Si la propriété est absente, la QoS 2 est prise en charge. Un client qui publie ensuite au-dessus du maximum annoncé viole le protocole, et le broker le déconnecte avec le reason code 0x9B (QoS not supported). En MQTT 3.1.1, cette propriété n'existe pas : les clients le découvrent à leurs dépens.
Les brokers plafonnent la QoS pour de bonnes raisons : la QoS 2 exige davantage d'état stocké et quatre paquets par message à chaque saut, ce qui pèse lourd sur une infrastructure partagée et multi-tenant.
Tester la QoS maximum MQTT sur le serveur MQTT public gratuit
Le serveur MQTT public gratuit broker.connectmq.com prend en charge les QoS 0 à 2 : c'est donc un bon endroit pour observer les rétrogradations dues à la combinaison publication/abonnement. Le flag -d fait afficher aux outils Mosquitto les paquets du protocole, y compris la QoS accordée dans le SUBACK.
Terminal 1, abonnement en demandant la QoS 1 :
mosquitto_sub -d -h broker.connectmq.com -p 1883 -i mq-sub-u3x7 -q 1 \
-t 'connectmq/demo/u3x7/#' -F 'qos=%q %t %p'
Dans la sortie de débogage, cherchez une ligne comme Client mq-sub-u3x7 received SUBACK suivie de Subscribed (mid: 1): 1. Le dernier nombre est la QoS accordée.
Terminal 2, publication à chaque niveau :
for q in 0 1 2; do
mosquitto_pub -h broker.connectmq.com -p 1883 -i mq-pub-u3x7 -q $q \
-t connectmq/demo/u3x7/test -m "published at qos $q"
done
Le terminal 1 affiche qos=0, qos=1 et qos=1. La publication en QoS 2 a été rétrogradée à 1 sur le chemin vers ce subscriber, car c'est ce que demandait l'abonnement. Relancez le subscriber avec -q 2 et la troisième ligne devient qos=2.
Vérifier la QoS accordée et la QoS maximum dans le code
Ce script paho-mqtt 2.x se connecte en MQTT 5, affiche la Maximum QoS annoncée par le broker si elle est présente, s'abonne en QoS 2 et affiche ce qui lui a été accordé :
import uuid
import paho.mqtt.client as mqtt
BROKER = "broker.connectmq.com"
TOPIC = "connectmq/demo/u3x7/check"
def on_connect(client, userdata, flags, reason_code, properties):
max_qos = getattr(properties, "MaximumQoS", None)
if max_qos is None:
print("CONNACK: no Maximum QoS property, QoS 2 supported")
else:
print(f"CONNACK: broker maximum QoS is {max_qos}")
client.subscribe(TOPIC, qos=2)
def on_subscribe(client, userdata, mid, reason_code_list, properties):
rc = reason_code_list[0]
if rc.is_failure:
print("subscription refused:", rc)
else:
print(f"SUBACK: requested 2, granted {rc.value}")
client.disconnect()
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"qoscheck-{uuid.uuid4().hex[:8]}",
protocol=mqtt.MQTTv5)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.connect(BROKER, 1883, keepalive=30)
client.loop_forever()
Exécutez le même script contre votre broker de production avec vos vrais identifiants avant de vous fier à un niveau de QoS. Cela prend quelques secondes et élimine les suppositions.
QoS des messages retenus et des messages Will
La même règle du minimum s'applique aux messages que le broker envoie de sa propre initiative. Un retained message est stocké avec la QoS à laquelle il a été publié, et un nouveau subscriber le reçoit à la plus basse entre cette QoS et la QoS accordée à son abonnement. Un Last Will est publié à la QoS de will définie dans le CONNECT, et chaque subscriber le reçoit là encore à la plus basse des deux. Si la QoS maximum du broker est inférieure à la QoS de will demandée, un broker MQTT 5 peut refuser la connexion avec le reason code 0x9B : gardez donc la QoS du will dans la limite annoncée.
Check-list pratique
- Choisissez la QoS de chaque topic en fonction du coût d'un message perdu ou dupliqué.
- Publiez à cette QoS ; les subscribers ne peuvent pas l'augmenter.
- Vérifiez la QoS accordée dans le SUBACK et journalisez-la lorsqu'elle est inférieure à la demande.
- En MQTT 5, lisez la Maximum QoS dans le CONNACK et limitez vos publications à cette valeur.
- Concevez vos consommateurs pour la QoS réellement obtenue : idempotents en QoS 1 (voir les messages dupliqués MQTT), tolérants aux trous en QoS 0.
- Évitez les abonnements qui se chevauchent avec des QoS différentes sur un même client.
Dépanner les problèmes de QoS
Client déconnecté juste après une publication. Si le reason code est 0x9B, vous avez publié au-dessus du maximum du broker. Baissez la QoS ou passez à une offre ou à un broker qui la prend en charge. La liste complète des codes se trouve dans les reason codes MQTT.
Le subscriber reçoit en QoS 0 alors qu'il s'est abonné en QoS 1. Le publisher utilise la QoS 0. Corrigez-le à la source.
La bibliothèque signale un succès mais des messages sont perdus. Certaines bibliothèques ignorent la QoS accordée. Vérifiez vous-même le SUBACK comme dans le script ci-dessus.
La QoS 2 est lente. Chaque message nécessite quatre paquets par saut. Pour une télémétrie à haut débit, la QoS 1 avec déduplication offre généralement un meilleur débit.
Les règles normatives figurent dans la spécification OASIS MQTT 5.0, dans les sections consacrées aux propriétés SUBACK et CONNACK.
Limites de QoS des offres ConnectMQ
ConnectMQ est explicite sur la QoS de chaque offre. L'offre Serverless gratuite prend en charge la QoS jusqu'à 1, l'offre Serverless payante ajoute la QoS 2 ainsi que des messages plus volumineux et les shared subscriptions, et les options Dedicated, BYOC et Self Managed Enterprise vous donnent un cluster isolé. Le serveur MQTT public gratuit autorise les QoS 0 à 2 pour vos expérimentations. Exécutez le script de vérification avec vos identifiants ConnectMQ pour confirmer ce que rapporte votre connexion. Si vous comparez des fournisseurs, notre présentation du broker MQTT managé et le tutoriel MQTT sont de bonnes lectures pour la suite.
Démarrer avec ConnectMQ
Créez gratuitement un broker sur app.connectmq.com avec l'offre Serverless, sans carte bancaire. Commencez en QoS 0 et 1, puis passez à l'offre payante pour la QoS 2 lorsque la charge de votre broker MQTT cloud exige une livraison exactement une fois.
Questions fréquentes
Qu'est-ce que la QoS effective en MQTT ?
C'est la QoS utilisée pour livrer un message à un subscriber : la plus basse entre la QoS de publication et la QoS accordée à l'abonnement.
Un subscriber peut-il obtenir une QoS plus élevée que celle du publisher ?
Non. Un message publié en QoS 0 est toujours livré en QoS 0, quel que soit l'abonnement.
Comment connaître la QoS maximum du broker ?
En MQTT 5, lisez la propriété Maximum QoS dans le CONNACK ; si elle est absente, la QoS 2 est prise en charge. En MQTT 3.1.1, vérifiez la QoS accordée dans le SUBACK.
Que se passe-t-il si je publie au-dessus de la QoS maximum ?
Un broker MQTT 5 déconnecte le client avec le reason code 0x9B, QoS not supported.



