MQTT QoS (Quality of Service), bir client'ın yayın yaparken veya abone olurken talep ettiği teslimat garantisidir. Bu rehberde QoS 0, 1 ve 2'nin tam olarak hangi paketleri değiş tokuş ettiğini, bir subscriber'a ulaşan QoS'un neden yayınladığınızdan düşük olabileceğini, oturumların çevrimdışı client'lar için mesajları nasıl kuyruğa aldığını ve tüm bunları broker.connectmq.com üzerinde Python ile nasıl test edeceğinizi göreceksiniz.
MQTT'nin kendisi size yeniyse önce MQTT Broker Nedir? yazısıyla başlayın ve buraya dönün.
MQTT QoS Gerçekte Neyi Garanti Eder?
MQTT, TCP üzerinde çalışır; bu yüzden tek bir bağlantı içinde baytlar kaybolmaz ve sırası bozulmaz. QoS başka bir şeyle ilgilidir: bir teslimatın ortasında bağlantı koptuğunda ne olacağı ve alıcının aynı mesajı iki kez alıp alamayacağı.
İki nokta sıklıkla yanlış anlaşılır:
- QoS uçtan uca değil, atlama (hop) bazlıdır. Publisher'ın QoS'u publisher'dan broker'a olan ayağı yönetir. Abonelik QoS'u ise broker'dan subscriber'a olan ayağı yönetir. Her ikisinde de aracı broker'dır.
- Daha yüksek QoS varsayılan olarak "daha iyi" değildir. Her seviye paket, durum ve gecikme ekler. Doğru seçim, kaybolan veya tekrarlanan bir mesajın size neye mal olduğuna bağlıdır.
| Seviye | Ad | Garanti | Mesaj başına paket (tek ayak) | Tekrar mümkün mü? |
|---|---|---|---|---|
| QoS 0 | En fazla bir kez | En iyi çaba, onay yok | 1 | Hayır, ancak kayıp mümkün |
| QoS 1 | En az bir kez | Teslim edilir, tekrarlanabilir | 2 | Evet |
| QoS 2 | Tam olarak bir kez | Bir kez teslim edilir, tekrar yok | 4 | Hayır |
QoS 0: En Fazla Bir Kez
QoS 0 "gönder ve unut" mantığıyla çalışır. Gönderen, PUBLISH paketini sokete yazar ve hemen unutur. Paket tanımlayıcısı yoktur, onay da yoktur.
Publisher Broker
| |
|------ PUBLISH (QoS 0) ---->|
| | (no reply, nothing stored)
Paket hâlâ işletim sistemi tamponundayken TCP bağlantısı koparsa mesaj kaybolur ve kimse fark etmez. Kulağa kötü geliyor; ancak iki saniyede bir gönderilen bir sıcaklık ölçümünde bir sonraki ölçüm kaybolanın yerini zaten alır. QoS 0, kısıtlı cihazlarda en düşük gecikmeyi ve en az ek yükü sağlar.
QoS 1: En Az Bir Kez
QoS 1'de gönderen bir paket tanımlayıcısı atar ve alıcı aynı tanımlayıcıyı taşıyan bir PUBACK ile yanıt verene kadar mesajı saklar.
Publisher Broker
| |
|-- PUBLISH (QoS 1, id=7) -->| broker stores and forwards
|<------- PUBACK (id=7) -----|
| | publisher deletes message 7
PUBACK hiç gelmezse (örneğin bağlantı koparsa) gönderen, yeniden bağlandıktan sonra PUBLISH'i DUP bayrağı ayarlı olarak tekrar gönderir. Püf noktası şu: alıcı ilk kopyayı zaten işlemiş olabilir, dolayısıyla mesajı iki kez görür. QoS 1'in en az bir kez anlamına gelmesinin nedeni budur.
QoS 1, çoğu IoT sisteminin beygiridir. Tüketicilerinizi idempotent yapın (örneğin payload'a bir mesaj ID'si veya zaman damgası ekleyip tekrarları yok sayın); genellikle ihtiyacınız olan tek şey QoS 1'dir.
QoS 2: Tam Olarak Bir Kez
QoS 2, her iki tarafın da mesajın tam olarak bir kez teslim edildiği konusunda uzlaşması için dört adımlı bir el sıkışma kullanır.
Publisher Broker
| |
|--- PUBLISH (QoS 2, id=9) --->| broker stores id 9, does not forward twice
|<------- PUBREC (id=9) -------| "received"
|-------- PUBREL (id=9) ------>| "release it, I will not resend"
|<------- PUBCOMP (id=9) ------| "complete", both sides drop id 9
Her adım ne yapar:
- PUBLISH: Gönderen mesajı saklar ve bir paket tanımlayıcısıyla gönderir.
- PUBREC: Alıcı tanımlayıcıyı kaydeder. Aynı ID ile tekrarlanan bir PUBLISH gelirse tanınır ve yeniden teslim edilmez.
- PUBREL: Gönderen mesajı siler ve bundan sonra yalnızca tanımlayıcıyı hatırlar.
- PUBCOMP: Alıcı tanımlayıcıyı unutur. Alışveriş tamamlanır.
Bedeli, mesaj başına iki gidiş-dönüş ve akış tamamlanana kadar her iki tarafta tutulan durumdur. Bir tekrarın gerçek zarara yol açacağı ve tüketiciyi idempotent yapamadığınız durumlarda QoS 2 kullanın; örneğin bir sayacı artıran veya bir faturalama olayını tetikleyen komutlar.
MQTT QoS Düşürme: İstediğiniz QoS'u Neden Alamayabilirsiniz?
Bir subscriber'ın aldığı QoS, publisher'ın kullandığı QoS ile aynı olmak zorunda değildir. Üç değer birbirini etkiler.
Geçerli QoS = min(yayın QoS'u, abonelik QoS'u)
Broker bir mesajı iletirken, orijinal PUBLISH'teki QoS ile abonelik için verilen QoS'tan düşük olanını kullanır.
| Publisher QoS | Abonelik QoS | Subscriber'a teslim edilen |
|---|---|---|
| 0 | 2 | 0 |
| 1 | 2 | 1 |
| 2 | 1 | 1 |
| 2 | 0 | 0 |
| 2 | 2 | 2 |
Dolayısıyla uçtan uca tam olarak bir kez teslimata ihtiyacınız varsa hem publisher'ın hem de her subscriber'ın QoS 2 kullanması gerekir. Tek bir QoS 0 aboneliği, o subscriber'ın akışını sessizce "en iyi çaba"ya çevirir.
Broker'ın Maximum QoS değeri (MQTT 5)
MQTT 5'te broker, CONNACK paketinde bir Maximum QoS bildirebilir. Bu property yoksa client, QoS 2'nin desteklendiğini varsayabilir. Varsa client bu seviyenin üzerinde yayın yapmamalıdır ve broker abonelikleri en fazla bu seviyede verir (verilen QoS'u SUBACK size söyler).
ConnectMQ'da bu, nereye bağlandığınıza bağlıdır:
| Ortam | Maximum QoS |
|---|---|
| broker.connectmq.com üzerindeki public test alanı | QoS 2 |
| Serverless (Free) planı | QoS 1 |
| Serverless (Paid) planı | QoS 2 |
| Dedicated, BYOC, Self Managed Enterprise | QoS 2 |
Varsaymak yerine her zaman SUBACK'teki verilen QoS'u kontrol edin. Çoğu client kütüphanesi bunu subscribe callback'inde sunar. Kuralların tam hali docs.oasis-open.org adresindeki MQTT 5 spesifikasyonunda açıklanır. Diğer CONNACK property'lerine genel bir bakış için MQTT 5 Özellikleri yazısına göz atın.
Oturumlar, Session Expiry ve Çevrimdışı Kuyruk
QoS, mesajları bir bağlantı kopmasına karşı yalnızca oturum bu kopmadan sağ çıkarsa korur. Oturum, broker'ın bir client için tuttuğu durumdur: abonelikleri, yoldaki (in-flight) QoS 1/2 mesajları ve client çevrimdışıyken kuyruğa alınan mesajlar.
- MQTT 3.1.1 Clean Session bayrağını kullanır.
cleanSession=truebağlantı kesildiğinde oturumu siler.cleanSession=falsebroker'dan oturumu saklamasını ister. - MQTT 5 bunu Clean Start (bağlanırken sıfırdan başlayıp başlamamak) ve Session Expiry Interval (oturumun bağlantı kesildikten sonra kaç saniye yaşayacağı) olarak ikiye ayırır.
Kalıcı bir oturum varken ve client çevrimdışıyken broker, aboneliklerle eşleşen QoS 1 ve QoS 2 mesajlarını kuyruğa alır. QoS 0 mesajları çevrimdışı client'lar için kuyruğa alınmaz. Client aynı client ID ile ve clean start olmadan yeniden bağlandığında kuyruktaki mesajlar teslim edilir.
Subscriber (id=sensor-reader) Broker
|-- CONNECT clean_start=0, expiry=600 -->|
|-- SUBSCRIBE plant/# QoS 1 ------------>|
| ... connection lost ... |
| | PUBLISH plant/a QoS 1 -> queued
| | PUBLISH plant/b QoS 0 -> dropped
|-- CONNECT clean_start=0 --------------->|
|<-- CONNACK session_present=1 -----------|
|<-- PUBLISH plant/a ---------------------|
ConnectMQ'da session expiry plan başına sınırlandırılmıştır; public test alanında oturumlar en fazla 30 dakika yaşar. Ayrıca oturumların bellekte tutulduğunu unutmayın: broker yeniden başlatıldığında korunmazlar; bu nedenle kritik akışları session_present=0 ile yeniden bağlanmayı tolere edecek şekilde tasarlayın.
Doğru MQTT QoS Seviyesi Nasıl Seçilir?
| Kullanım senaryosu | Önerilen QoS | Neden |
|---|---|---|
| Yüksek frekanslı telemetri (sıcaklık, titreşim) | 0 | Bir sonraki örnek kaybolanın yerini alır; en düşük ek yük |
| Cihaz durumu, alarmlar, olaylar | 1 | Mutlaka ulaşmalı; tekrarları yok saymak kolay |
| Aktüatörlere komutlar (idempotent: "vanayı %40'a ayarla") | 1 | Aynı komutu tekrarlamak zararsızdır |
| Idempotent olmayan komutlar ("sayacı artır", "dağıt") | 2 | Bir tekrar sonucu değiştirir |
| Faturalama, sayaç okuma veya işlem olayları | 2 (veya tekilleştirme ID'li 1) | Tam olarak bir kez muhasebe |
Pratik bir kural: idempotent tüketicilerle varsayılan olarak QoS 1 kullanın, kaybetmeyi göze alabileceğiniz yüksek hızlı veri için QoS 0'a inin ve QoS 2'yi tekrarın bir hata olduğu az sayıdaki mesaj türüne saklayın.
Uygulamalı: Python'da MQTT QoS 1 ve QoS 2
Aşağıdaki betik paho-mqtt 2.x'i ve broker.connectmq.com'un public alanını (kullanıcı adı veya parola olmadan) kullanır. QoS 2 ile abone olur, bir mesajı QoS 1 ve bir mesajı QoS 2 ile yayınlar ve onayları loglar. Kütüphaneyi pip install "paho-mqtt>=2.0" ile kurun.
import time
import uuid
import paho.mqtt.client as mqtt
BROKER = "broker.connectmq.com"
UID = uuid.uuid4().hex[:8]
TOPIC = f"connectmq/demo/{UID}/qos"
def on_connect(client, userdata, flags, reason_code, properties):
print("CONNACK:", reason_code)
if properties is not None and hasattr(properties, "MaximumQoS"):
print("Broker Maximum QoS:", properties.MaximumQoS)
client.subscribe(f"{TOPIC}/#", qos=2)
def on_subscribe(client, userdata, mid, reason_code_list, properties):
print("SUBACK granted:", [rc.value for rc in reason_code_list])
def on_message(client, userdata, msg):
print(f"Received {msg.topic} QoS={msg.qos} payload={msg.payload.decode()}")
def on_publish(client, userdata, mid, reason_code, properties):
print(f"Publish flow complete for mid={mid}")
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id=f"qos-demo-{UID}",
protocol=mqtt.MQTTv5,
)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message
client.on_publish = on_publish
client.connect(BROKER, 1883, keepalive=30)
client.loop_start()
time.sleep(2)
client.publish(f"{TOPIC}/one", "hello at least once", qos=1).wait_for_publish()
client.publish(f"{TOPIC}/two", "hello exactly once", qos=2).wait_for_publish()
time.sleep(2)
client.loop_stop()
client.disconnect()
QoS 1 için on_publish, PUBACK geldiğinde tetiklenir. QoS 2 için ise yalnızca dört adımlı el sıkışmanın sonunda, PUBCOMP'tan sonra tetiklenir. Maximum QoS satırı yazdırılmazsa broker bu property'yi göndermemiştir; bu da QoS 2'ye izin verildiği anlamına gelir.
Paketleri Mosquitto CLI ile izleyin
Eclipse Mosquitto komut satırı araçları -d ile her paketi yazdırır; bu da yukarıdaki akışları görünür kılar. Bir terminalde:
mosquitto_sub -h broker.connectmq.com -p 1883 -i qos-sub-a1b2 -t "connectmq/demo/a1b2/#" -q 2 -v -d
İkinci bir terminalde önce QoS 1, ardından QoS 2 ile yayın yapın:
mosquitto_pub -h broker.connectmq.com -p 1883 -i qos-pub-a1b2 -t "connectmq/demo/a1b2/q1" -q 1 -m "hello1" -d
mosquitto_pub -h broker.connectmq.com -p 1883 -i qos-pub-a1b2 -t "connectmq/demo/a1b2/q2" -q 2 -m "hello2" -d
Publisher çıktısı, daha önce anlatılan dizileri birebir gösterir:
Client qos-pub-a1b2 sending PUBLISH (d0, q1, r0, m1, 'connectmq/demo/a1b2/q1', ... (6 bytes))
Client qos-pub-a1b2 received PUBACK (Mid: 1, RC:0)
...
Client qos-pub-a1b2 sending PUBLISH (d0, q2, r0, m1, 'connectmq/demo/a1b2/q2', ... (6 bytes))
Client qos-pub-a1b2 received PUBREC (Mid: 1)
Client qos-pub-a1b2 sending PUBREL (m1)
Client qos-pub-a1b2 received PUBCOMP (Mid: 1, RC:0)
a1b2 yerine kendi rastgele dizenizi yazın. Public alandaki her şey herkes tarafından okunabilir; bu yüzden orada asla hassas veri yayınlamayın. QoS düşürmeyi denemek için -q 0 ile abone olup -q 2 ile yayın yapın: subscriber'ın debug çıktısı teslim edilen PUBLISH'te q0 gösterecektir. Daha fazla public broker ipucu Ücretsiz Public MQTT Broker yazısında.
Sık Yapılan QoS Hataları
- Bir subscriber QoS 0 kullanırken uçtan uca QoS 2 varsaymak. En zayıf halka kazanır.
- Yüksek hızlı telemetri için QoS 2 kullanmak. Ayak başına mesaj başına dört paket hızla birikir ve yoldaki mesaj penceresi (Receive Maximum) dolar.
- Kalıcı oturumlarla rastgele client ID'ler kullanmak. Çevrimdışı kuyruk yalnızca client aynı client ID ile yeniden bağlanırsa çalışır. Yeni bir rastgele ID, yeni ve boş bir oturum oluşturur.
- SUBACK'teki verilen QoS'u yok saymak. QoS 1 ile sınırlı bir planda QoS 2 aboneliği QoS 1 olarak verilir.
ConnectMQ ile Başlayın
Public test broker'ı MQTT QoS'u öğrenmek için harikadır; ancak üretim trafiği kimlik bilgileri olan özel bir broker'a aittir. app.connectmq.com adresinden ücretsiz kaydolun (Serverless planı, kredi kartı gerekmez), bir broker oluşturun ve üretilen kullanıcı adı, parola ve client ID'yi kullanın. QoS 2'ye, daha fazla bağlantıya veya daha büyük mesajlara ihtiyaç duyduğunuzda Serverless (Paid) veya Dedicated'a geçin.
Sık Sorulan Sorular
Varsayılan MQTT QoS seviyesi nedir?
Çoğu client kütüphanesi hem yayın hem abonelik için varsayılan olarak QoS 0 kullanır. Kodu okuyan herkes için davranışın net olması adına QoS'u kodunuzda açıkça belirtin.
QoS 2, MQTT'yi yavaşlatır mı?
Evet. QoS 2, her ayakta mesaj başına dört paket ve iki gidiş-dönüş gerektirir; QoS 1'de iki, QoS 0'da ise tek paket vardır. Çoğu telemetri için QoS 0 veya 1 daha iyi verim sağlar.
QoS 2 ile yayınladığım halde subscriber'ım neden QoS 1 aldı?
Teslim edilen QoS, yayın QoS'u ile verilen abonelik QoS'unun en küçüğüdür. Aboneliğiniz QoS 1 olarak verilmiştir; ya siz bunu talep ettiniz ya da ConnectMQ Serverless (Free) planında olduğu gibi broker'ın Maximum QoS değeri 1'dir.
QoS 0 mesajları çevrimdışı client'lar için kuyruğa alınır mı?
Hayır. Broker'lar kalıcı oturumu olan client'lar için yalnızca QoS 1 ve QoS 2 mesajlarını kuyruğa alır. Çevrimdışı bir client'a giden QoS 0 mesajları düşürülür.
broker.connectmq.com üzerinde QoS 2 kullanabilir miyim?
Evet. Anonim public alan QoS 0, 1 ve 2'yi destekler. Özel broker'lar Serverless (Paid) ve üstü planlarda QoS 2'yi desteklerken ücretsiz Serverless planı QoS 1 ile sınırlıdır.



