MQTT Temelleri

MQTT 5 Abonelik Seçenekleri: No Local, Retain As Published ve Retain Handling

Her MQTT 5 abonelik seçeneğinin ne yaptığı, ne zaman kullanılacağı ve MQTT.js ile paho-mqtt'de nasıl ayarlanacağı; herkese açık bir MQTT 5 broker'a karşı çalıştırılabilir örneklerle.

Bir SUBSCRIBE paketindeki No Local, Retain As Published ve Retain Handling bayraklarını gösteren MQTT abonelik seçenekleri 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 abonelik seçenekleri, MQTT 5.0 ile gelen ve broker'ın mesajları size nasıl ileteceğini kontrol eden abonelik başına bayraklardır: kendi yayınlarınızı alıp almayacağınız, retain bayrağının korunup korunmayacağı ve abone olduğunuzda retained mesajların yeniden gönderilip gönderilmeyeceği. Bu yazının sonunda her seçeneğin ne yaptığını, hangi gerçek sorunları çözdüğünü ve JavaScript ile Python'da nasıl ayarlanacağını öğrenmiş olacaksınız.

Abonelik Seçenekleri Nerede Bulunur?

MQTT 3.1.1'de bir SUBSCRIBE paketi bir topic filtresi ve istenen QoS'u tutan bir bayt taşır. MQTT 5.0 bu baytı korur, ancak boştaki bitleri yeni seçenekler için kullanır. Bir SUBSCRIBE içindeki her topic filtresi kendi seçenek baytına sahiptir:

Bitler Seçenek Değerler
0–1 Maximum QoS 0, 1 veya 2
2 No Local 0 = kapalı, 1 = açık
3 Retain As Published 0 = kapalı, 1 = açık
4–5 Retain Handling 0, 1 veya 2
6–7 Ayrılmış 0 olmalı

Seçenekler filtre başına olduğundan, tek bir istemci aynı pakette chat/room1 topic'ine No Local açık olarak, config/# topic'ine ise farklı bir retain davranışıyla abone olabilir. Tam tanımlar OASIS MQTT 5.0 spesifikasyonunda yer alır. Seçenekler yalnızca istemci protokol sürümü 5 ile bağlandığında mevcuttur; bir 3.1.1 bağlantısı bunları ifade edemez. Sürümün geri kalanı hakkında bilgi için MQTT 5 özellikleri genel bakışına göz atın.

Maximum QoS

Bu, MQTT 3.1.1'den bilinen QoS'tur; anlamını netleştirmek için yeniden adlandırılmıştır. Broker'ın bu abonelikte mesajları ileteceği en yüksek QoS'u ifade eder. Maximum QoS değeri 1 olan bir aboneliğe QoS 2 ile yayınlanan bir mesaj QoS 1 olarak ulaşır. QoS 0 ile yayınlanan bir mesaj hiçbir zaman yükseltilmez. MQTT QoS seviyeleri sizin için yeniyse önce o rehberi okuyun, çünkü iletimle ilgili sürprizlerin çoğu bu düşürme kuralından kaynaklanır.

No Local: Kendi Mesajlarınızı Almayı Durdurun

Varsayılan olarak bir istemci, aynı zamanda abone olduğu bir topic'e yayın yaparsa broker mesajı ona geri gönderir. No Local ayarlandığında broker, mesajı onu yayınlayan bağlantıya iletmez.

Tipik durumlar:

  • Sohbet ve iş birliği uygulamaları. Her katılımcı chat/room1 topic'ine hem yayın yapar hem de abone olur. No Local olmadan her kullanıcı kendi mesajını iki kez görür: bir kez yerel arayüzden, bir kez de broker'ın yankısı olarak.
  • İki yönlü senkronizasyon. devices/+/config üzerinde hem yayın yapan hem de dinleyen bir servis, aksi takdirde kendi güncellemelerini işler ve döngüye girebilir.
  • Köprüler. Aynı broker'a abone olup yeniden yayın yapan bir köprü mesaj döngüleri oluşturabilir; köprü tarafında No Local bu döngüleri kırar.

Akılda tutulması gereken iki kural var. No Local, client ID ile tanımlanan bağlantı başına çalışır; dolayısıyla aynı uygulamanın çalıştırdığı iki farklı istemci yine birbirlerinin mesajlarını alır. Ayrıca bir shared subscription'da ($share/...) No Local ayarlamak protokol hatasıdır, çünkü bir grup için "yerel" kavramının anlamı yoktur.

Retain As Published

Broker canlı bir mesajı abonelere iletirken, yayıncı ayarlamış olsa bile varsayılan olarak RETAIN bayrağını temizler. Bayrak yalnızca broker'ın yeni bir abonelik nedeniyle gönderdiği mesajlarda (depolanan retained message) ayarlıdır. Bu varsayılan davranış, abonelerin "bu depolanan son değer" ile "bu az önce oldu" arasında ayrım yapmasını sağlar.

Retain As Published açıkken broker, RETAIN bayrağını tam olarak yayıncının ayarladığı gibi korur. Buna esas olarak abone mesajları başka bir yere yeniden yayınlıyorsa ve retained durumunun korunması gerekiyorsa ihtiyaç duyarsınız:

  • Retained durumu yansıtan broker'lar arası köprüler.
  • Retained mesajları kendisi de dikkate alan ikinci bir sisteme ileten ağ geçitleri ve proxy'ler.
  • Yayıncının gerçekte ne gönderdiğini göstermek isteyen hata ayıklama araçları.

Sıradan uygulama aboneleri için bu seçeneği kapalı bırakın.

Retain Handling: Retained Tekrarlarını Kontrol Edin

Retained mesajlar, bir istemci abone olduğunda ona gönderilir. Retain Handling bunun ne zaman olacağına karar verir:

Değer Davranış Ne zaman kullanılır
0 Her abonelikte retained mesajları gönder (varsayılan) Mevcut duruma ihtiyaç duyan panolar ve tüketiciler
1 Retained mesajları yalnızca abonelik daha önce yoksa gönder Yeniden bağlanırken tekrar abone olan, kalıcı oturumlu istemciler
2 Bu abonelik için retained mesajları asla gönderme Yalnızca yeni mesajlarla ilgilenen olay işleyiciler

Değer 1 ince bir sorunu çözer. Kalıcı oturuma sahip bir cihaz yeniden bağlanır ve önlem olarak tekrar abone olur. Değer 0 ile her retained mesajı yeniden alır; bunlar yapılandırma mesajlarıysa onları yeniden uygulayabilir. Değer 1 ile broker, retained mesajları yalnızca abonelik gerçekten yeniyse tekrar gönderir.

Değer 2, günlükleyiciler ve alarm servisleri için kullanışlıdır. Bir alarm servisi alarms/# topic'ine abone olursa ve broker saatler öncesinden kalma retained alarmlar tutuyorsa, değer 0 servisin her yeniden başlatıldığında eski alarmları tetiklemesine neden olur.

MQTT Abonelik Seçeneklerini Kodda Ayarlamak

Her iki örnek de broker.connectmq.com adresindeki herkese açık test broker'ına TLS üzerinden MQTT 5 ile bağlanır. Kendinize ait benzersiz bir topic öneki kullanın; herkese açık alan herkes tarafından okunabilir, bu yüzden veriyi zararsız tutun.

MQTT.js (Node.js)

// npm install mqtt
const mqtt = require("mqtt");

const prefix = "connectmq/demo/c41e";
const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
  clientId: "subopts-js-c41e",
  protocolVersion: 5,
});

client.on("connect", () => {
  // No Local: kendi sohbet mesajlarımızı bize geri yansıtma
  client.subscribe(`${prefix}/chat/room1`, { qos: 1, nl: true }, (err, granted) => {
    if (err) return console.error(err);
    console.log("chat granted:", granted);
    client.publish(`${prefix}/chat/room1`, "hello from js", { qos: 1 });
  });

  // Retain Handling 2: depolanan alarmları yok say, yalnızca yenileri al
  client.subscribe(`${prefix}/alarms/#`, { qos: 1, rh: 2 });

  // Retain As Published: RETAIN bayrağını gönderildiği gibi koru
  client.subscribe(`${prefix}/config/#`, { qos: 1, rap: true, rh: 1 });
});

client.on("message", (topic, payload, packet) => {
  console.log(`${topic} retain=${packet.retain} -> ${payload.toString()}`);
});

Betiği çalıştırdığınızda "hello from js" yazısını görmezsiniz, çünkü No Local yankıyı bastırır. Aynı sohbet topic'ine başka bir istemciden yayın yaptığınızda mesaj görünür.

Python paho-mqtt 2.x

import ssl
import paho.mqtt.client as mqtt
from paho.mqtt.subscribeoptions import SubscribeOptions

PREFIX = "connectmq/demo/c41e"

def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code.is_failure:
        print("Connect failed:", reason_code)
        return
    client.subscribe([
        (f"{PREFIX}/chat/room1", SubscribeOptions(qos=1, noLocal=True)),
        (f"{PREFIX}/alarms/#", SubscribeOptions(
            qos=1, retainHandling=SubscribeOptions.RETAIN_DO_NOT_SEND)),
        (f"{PREFIX}/config/#", SubscribeOptions(
            qos=1, retainAsPublished=True,
            retainHandling=SubscribeOptions.RETAIN_SEND_IF_NEW_SUB)),
    ])

def on_subscribe(client, userdata, mid, reason_code_list, properties):
    print("SUBACK:", [str(rc) for rc in reason_code_list])

def on_message(client, userdata, msg):
    print(f"{msg.topic} retain={msg.retain} -> {msg.payload.decode()}")

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id="subopts-py-c41e", protocol=mqtt.MQTTv5)
client.tls_set(cert_reqs=ssl.CERT_REQUIRED)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message
client.connect("broker.connectmq.com", 8883, keepalive=60)
client.loop_forever()

Davranışı Doğrulamak

Birkaç dakikada çalıştırabileceğiniz hızlı bir test planı:

  1. Herhangi bir istemciden, örneğin ConnectMQ portalındaki tarayıcı içi MQTT istemcisinden veya mosquitto_pub -r ile, connectmq/demo/c41e/alarms/pump1 topic'ine retained bir mesaj yayınlayın.
  2. Python betiğini başlatın. Alarm aboneliği Retain Handling 2 kullandığından retained alarm iletilmez.
  3. Retained olmayan yeni bir alarm yayınlayın. Hemen ulaşır.
  4. .../config/rate topic'ine retained bir mesaj yayınlayın. Retain As Published açık olduğundan betik canlı mesaj için retain=True yazdırır.
  5. Başka hiçbir şeyi değiştirmeden betiği yeniden başlatın ve davranışın tekrarlanabilir olduğunu doğrulayın.

Yaygın Hatalar

  • MQTT 3.1.1 ile bağlanmak. Kütüphaneler 3.1.1 bağlantısında abonelik seçeneklerini sessizce yok sayar. Her zaman protocolVersion: 5 veya protocol=mqtt.MQTTv5 ayarlayın.
  • Shared subscription'larda No Local. Broker bunu protokol hatası olarak değerlendirir ve bağlantıyı kapatır.
  • Retain Handling 1'in temiz oturumlarla çalışmasını beklemek. Oturum her seferinde yeniyse her abonelik de yenidir; bu yüzden değer 1, değer 0 gibi davranır.
  • Panolarda Retain As Published kullanmak. Bu durumda pano depolanan bir değeri yenisinden ayırt edemez. Mesajları iletmiyorsanız varsayılanı koruyun.
  • SUBACK'i görmezden gelmek. 0x80 veya 0x87 gibi bir reason code, aboneliğin reddedildiği anlamına gelir. SUBACK reason code'larını günlüğe kaydedin.

Role Göre Seçenek Seçimi

İstemci rolü Max QoS No Local Retain As Published Retain Handling
Pano 1 kapalı kapalı 0
Sohbet katılımcısı 1 açık kapalı 0 veya 2
Alarm servisi 1 kapalı kapalı 2
Kalıcı oturumlu cihaz 1 kapalı kapalı 1
Köprü veya yönlendirici 2 açık açık 0

Bu seçenekler, ConnectMQ ve diğer MQTT 5 broker'larını 3.1.1 öncüllerine göre üzerine geliştirme yapmayı kolaylaştıran unsurlardan biridir: eskiden uygulama düzeyinde filtreleme gerektiren davranış artık SUBSCRIBE paketindeki bir bayraktır. Bunları MQTT wildcard'ları yazısındaki iyi topic tasarımıyla birleştirin ve temelleri hâlâ öğreniyorsanız MQTT eğitimini elinizin altında tutun.

ConnectMQ ile Başlayın

Abonelik seçeneklerini herkese açık MQTT test broker'ı üzerinde test edin, ardından MQTT 5.0, TLS ve oluşturulmuş kimlik bilgileriyle özel bir yönetilen MQTT broker'a geçin. app.connectmq.com adresinde kredi kartı gerekmeden ücretsiz bir Serverless broker oluşturun.

Sık Sorulan Sorular

MQTT abonelik seçenekleri MQTT 3.1.1'de mevcut mu?

Hayır. MQTT 3.1.1 yalnızca istenen QoS'u taşır. No Local, Retain As Published ve Retain Handling bir MQTT 5.0 bağlantısı gerektirir.

Her abonelik seçeneğinin varsayılan değeri nedir?

No Local ve Retain As Published varsayılan olarak kapalıdır; Retain Handling ise varsayılan olarak 0'dır ve her abonelikte retained mesajları gönderir. Bu, MQTT 3.1.1 davranışıyla örtüşür.

No Local etkinken neden hâlâ kendi mesajlarımı alıyorum?

MQTT 5 ile bağlandığınızı ve yayıncı ile abonenin aynı bağlantı olduğunu kontrol edin. Aynı süreç içinde olsa bile ikinci bir istemci yerel sayılmaz.

Abonelikten çıkmadan abonelik seçeneklerini değiştirebilir miyim?

Evet. Aynı topic filtresi için yeni bir SUBSCRIBE göndermek, mevcut aboneliğin seçeneklerini değiştirir. Retain Handling 1 ile abonelik zaten var olduğundan retained mesajlar yeniden gönderilmez.

İ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.