MQTT Temelleri

MQTT QoS Seviyeleri: Paket Akışları ve Örneklerle QoS 0, 1 ve 2

MQTT QoS için pratik bir rehber: QoS 0, 1 ve 2 kablo üzerinde nasıl çalışır, teslim edilen QoS neden istediğinizden düşük olabilir, oturumlar mesajları nasıl kuyruğa alır ve her kullanım senaryosu için hangi seviyeyi seçmelisiniz.

Bir client ile MQTT broker arasındaki MQTT QoS 0, 1 ve 2 paket akışlarını gösteren diyagram
Bunu kendi MQTT broker’ınızda çalıştırınFree planla özel, yönetilen bir MQTT broker alın ve hazır kod örnekleriyle başlayın.
Ücretsiz deneyin Kod örnekleri Kart gerekmez

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:

  1. PUBLISH: Gönderen mesajı saklar ve bir paket tanımlayıcısıyla gönderir.
  2. PUBREC: Alıcı tanımlayıcıyı kaydeder. Aynı ID ile tekrarlanan bir PUBLISH gelirse tanınır ve yeniden teslim edilmez.
  3. PUBREL: Gönderen mesajı siler ve bundan sonra yalnızca tanımlayıcıyı hatırlar.
  4. 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=true bağlantı kesildiğinde oturumu siler. cleanSession=false broker'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.

İlgili yazılar

MQTT'yi Kim İcat Etti? Petrol Boru Hatlarından IoT'ye Uzanan Tarih

MQTT, 1999'da IBM'den Andy Stanford-Clark ve Arcom'dan Arlen Nipper tarafından petrol boru hatlarını uydu üzerinden izlemek için icat edildi. Açık kaynağa, OASIS'e, ISO'ya ve bugünün yönetilen bulut broker'larına uzanan yolculuğunu izleyin.

7 dk okuma

MQTT Maksimum Mesaj Boyutu: Sınırlar ve Büyük Payload Stratejileri

MQTT teknik olarak 256 MB'lık bir paket taşıyabilir, ancak broker'lar, istemci kütüphaneleri ve cihazlar çok daha düşük sınırlar uygular. Gerçek sınırların nerede olduğunu, aşıldıklarında ne olduğunu ve büyük payload'ların nasıl gönderileceğini öğrenin.

6 dk okuma

Tüm yazılar →

Özel MQTT broker’ınız birkaç tık uzağınızda

Hesabınızı oluşturun, broker kimlik bilgilerinizi alın ve ilk cihazınızı bağlayın — kurulacak, yamalanacak ya da ölçeklendirilecek sunucu yok.