Broker testleri

MQTT 5 Topic Alias Nasıl Test Edilir

MQTT 5 topic alias'ları test edin: Topic Alias Maximum'u okuyun, alias'lı yayınları doğrulayın, tasarrufu ölçün ve Topic Alias invalid hatasını üretin.

Güncellendi · 8 dk okuma

MQTT 5 Topic Alias Nasıl Test Edilir

MQTT 5 topic alias'ları, uzun bir topic adını bağlantının geri kalanı boyunca 2 baytlık bir sayıyla değiştirir. İlk PUBLISH hem topic'i hem alias'ı taşır. Sonraki her PUBLISH boş bir topic ile birlikte alias'ı gönderir. Test etmek için broker'ın CONNACK içinde verdiği Topic Alias Maximum değerini okuyun, topic adıyla ve topic adı olmadan yayın yapın, subscriber'ların tam topic'i aldığını kontrol edin ve iki hata durumunu yeniden üretin: aralık dışındaki bir alias ve broker'ın tanımadığı bir alias.

Mekanizmanın kendisi MQTT topic alias'ları yazısında anlatılıyor. Bu makale test planıdır.

Alias'lar nasıl müzakere edilir

YönLimiti kim belirlerNeredeVarsayılan
İstemci → brokerBrokerCONNACK içinde Topic Alias Maximum0 (alias yok)
Broker → istemciİstemciCONNECT içinde Topic Alias Maximum0 (alias yok)

Doğru bir uygulamanın izlediği kurallar:

  • Alias değerleri 1'den müzakere edilen maksimuma kadardır. 0 asla geçerli değildir.
  • Eşlemeyi gönderen taraf seçer. Mevcut bir alias numarasıyla yeni bir topic göndermek o alias'ı yeniden eşler.
  • Eşlemeler bağlantıya ve yöne özgüdür. Oturum kalıcı olsa bile bağlantı kesilince kaybolurlar.
  • Boş topic'li bir PUBLISH, bu bağlantıda zaten eşlenmiş bir alias taşımalıdır.

Bir alias ne kadar tasarruf sağlar?

Tipik bir telemetri topic'i olan factory/line-3/press-07/telemetry/vibration (43 karakter), 20 baytlık bir payload ve QoS 1 alalım:

AlanTam topicAlias ile
Sabit başlık2 bayt2 bayt
Topic adı (2 baytlık uzunluk + metin)45 bayt2 bayt (boş)
Paket kimliği2 bayt2 bayt
Özellikler (uzunluk + Topic Alias)1 bayt4 bayt
Payload20 bayt20 bayt
Toplam70 bayt30 bayt

Bu, mesaj başına 40 bayt, yani paketin yarısından fazlası demektir. Saniyede bir mesajla tek bir cihaz günde yaklaşık 3,5 MB tasarruf eder. Tasarruf yalnızca topic'ler payload'lara göre uzunsa ve baytlar para ya da pil harcatıyorsa, örneğin hücresel, uydu veya LPWAN bağlantılarında önemlidir. 2 KB'lık payload'ların gezdiği bir LAN'da önemsizdir. Paket boyutu hesaplayıcı kendi topic'leriniz için rakamları gösterir; MQTT bant genişliği yükü yazısı da trafiği küçültmenin diğer yollarını ele alır. TLS kayıt başına kendi ek yükünü getirir, bu yüzden bütçe dar ise ölçümü hat üzerinde yapın.

Test 1: müzakere edilen maksimumu okuyun

Her şeyden önce broker'ın ne verdiğini loglayın. Broker'lar farklıdır: kimi çok sayıda alias'a izin verir, kimi yalnızca birkaçına, kimi de özelliği tamamen kapatır (maksimum 0). Kontrol etmeden alias kullanan bir istemcinin bağlantısı, hiç alias'a izin vermeyen broker'larda kesilir.

Mosquitto CLI'da -d CONNACK'i yazdırır, ancak özelliklerin çıktısı sürümden sürüme değişir. Bir betik daha güvenilirdir. Aşağıdaki test önce maksimumu yazdırır ve değer 0 ise durur.

Test 2: alias'lı yayınlar eksiksiz ulaşıyor

Bu paho-mqtt 2.x betiği tam topic ve alias 1 ile bir mesaj, boş topic ve alias 1 ile dört mesaj daha yayınlar ve normal bir subscriber'ın beşini de tam topic adıyla aldığını kontrol eder. Ardından yeniden bağlanır ve broker'ın tepkisini görmek için eskimiş alias'ı gönderir.

alias_test.py
import time, uuid
import paho.mqtt.client as mqtt
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes

HOST, PORT = "broker.connectmq.com", 1883
RUN = uuid.uuid4().hex[:8]
TOPIC = f"testmqtt/alias/{RUN}/factory/line-3/press-07/telemetry"
received = []

def client(cid, log):
    c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"{cid}-{RUN}", protocol=mqtt.MQTTv5)
    c.on_connect = lambda cl, u, f, rc, props: log.update(max=getattr(props, "TopicAliasMaximum", 0))
    c.on_disconnect = lambda cl, u, f, rc, props: log.update(disconnect=str(rc))
    return c

def alias_props(alias):
    p = Properties(PacketTypes.PUBLISH)
    p.TopicAlias = alias
    return p

# Subscriber: a normal client that does not accept aliases from the broker
sub_log = {}
sub = client("alias-sub", sub_log)
sub.on_message = lambda cl, u, msg: received.append((msg.topic, msg.payload.decode()))
sub.connect(HOST, PORT)
sub.loop_start()
sub.subscribe(TOPIC, qos=1)

# Test 1: negotiation + valid alias use
log = {}
pub = client("alias-pub", log)
pub.connect(HOST, PORT)
pub.loop_start()
time.sleep(1)
print("broker Topic Alias Maximum:", log.get("max"))
if not log.get("max"):
    raise SystemExit("broker does not accept topic aliases from clients (maximum 0)")

pub.publish(TOPIC, "m0", qos=1, properties=alias_props(1))      # set alias 1 = TOPIC
for i in range(1, 5):
    pub.publish("", f"m{i}", qos=1, properties=alias_props(1))  # topic omitted, alias only
time.sleep(2)
ok = received == [(TOPIC, f"m{i}") for i in range(5)]
print("PASS" if ok else "FAIL", "aliased messages arrive with the full topic:", len(received), "of 5")
pub.disconnect(); pub.loop_stop()

# Test 2: alias mappings do not survive a reconnect
received.clear()
log = {}
pub = client("alias-pub", log)
pub.connect(HOST, PORT)
pub.loop_start()
time.sleep(1)
pub.publish("", "after-reconnect", qos=1, properties=alias_props(1))  # unknown on this connection
time.sleep(2)
print("PASS" if not received else "FAIL", "stale alias after reconnect is not delivered;",
      "broker reaction:", log.get("disconnect", "no DISCONNECT, message dropped"))
pub.disconnect(); pub.loop_stop()

# Test 3: alias above the negotiated maximum (only possible if the maximum is below 65535)
if log.get("max", 0) < 65535:
    log2 = {}
    bad = client("alias-bad", log2)
    bad.connect(HOST, PORT)
    bad.loop_start()
    time.sleep(1)
    bad.publish(TOPIC, "too-high", qos=1, properties=alias_props(log2["max"] + 1))
    time.sleep(2)
    print("broker reaction to alias > maximum:", log2.get("disconnect", "none"))
    bad.loop_stop()

sub.disconnect(); sub.loop_stop()

Tipik bir çalıştırma şunu yazdırır:

Çıktı
broker Topic Alias Maximum: 65535
PASS aliased messages arrive with the full topic: 5 of 5
PASS stale alias after reconnect is not delivered; broker reaction: no DISCONNECT, message dropped

paho-mqtt alias'ları sizin yerinize yönetmez. Ayarladığınız alias'ı aynen gönderir ve broker'dan gelen alias'ları çözmez; bu yüzden bir paho subscriber'ında asla Topic Alias Maximum bildirmeyin. Bu durum onu negatif testler için de iyi bir araç yapar. Yine de paho, alias 0'ı yerel olarak reddeder (TopicAlias property value must be in the range 1-65535); broker'ın alias 0'a tepkisini test etmek için ham paket gönderebilen bir araca ihtiyacınız vardır.

MQTT.js ile otomatik alias'lar

MQTT.js 5 alias'ları sizin için atayabilir. autoAssignTopicAlias ile topic'leri, broker'ın maksimumu dahilinde en az son kullanılan (LRU) mantığıyla alias'lara eşler. Hat üzerinden neyin gittiğini doğrulamak için paketleri loglayın:

alias.mjs
import mqtt from "mqtt";

const topic = "testmqtt/alias/js-demo/factory/line-3/press-07/telemetry";
const client = mqtt.connect("mqtt://broker.connectmq.com:1883", {
  protocolVersion: 5,
  clientId: `alias-js-${Math.random().toString(16).slice(2, 10)}`,
  autoAssignTopicAlias: true,             // let MQTT.js pick and reuse aliases
  properties: { topicAliasMaximum: 10 },  // accept up to 10 aliases from the broker
});

// Log what actually goes over the wire
client.on("packetsend", (p) => {
  if (p.cmd === "publish") console.log(`sent topic="${p.topic}" alias=${p.properties?.topicAlias}`);
});

client.on("connect", (connack) => {
  console.log("broker Topic Alias Maximum:", connack.properties?.topicAliasMaximum ?? 0);
  let n = 0;
  const timer = setInterval(() => {
    client.publish(topic, JSON.stringify({ n, vibration: Math.random() }), { qos: 1 });
    if (++n === 5) {
      clearInterval(timer);
      setTimeout(() => client.end(), 500);
    }
  }, 300);
});

client.on("error", (err) => console.error("error:", err.message));

Beklenen çıktı: ilk satır alias=1 ile tam topic'i, sonraki dört satır ise alias=1 ile topic="" gösterir. Her satırda tam topic görünüyorsa broker maksimum 0 vermiş ve MQTT.js sessizce normal yayınlara dönmüştür. Bu doğru davranıştır ama hiçbir tasarruf yapmadığınız anlamına gelir. autoUseTopicAlias daha temkinli seçenektir: yalnızca sizin kaydettiğiniz alias'ları yeniden kullanır.

Test 3: hata durumları

Ne gönderiyorsunuzSpesifikasyon ne diyorİnsanların aradığı hata
Alias 0Protokol hatasıDISCONNECT 0x94 Topic Alias invalid
Müzakere edilen maksimumun üstünde aliasProtokol hatasıDISCONNECT 0x94 Topic Alias invalid
Boş topic, hiç eşlenmemiş aliasProtokol hatasıDISCONNECT 0x82 Protocol Error
Maksimum 0 iken herhangi bir aliasProtokol hatası0x94 ya da MQTT.js'te istemci tarafında Sending Topic Alias out of range
Yeniden bağlanma sonrası eskimiş alias"Hiç eşlenmemiş" ile aynı0x82 ya da mesaj sessizce kaybolur

Her broker aynı tepkiyi vermez. Bazıları reason code ile DISCONNECT gönderir, bazıları bağlantıyı kapatır ya da o tek mesajı haber vermeden atar. Yukarıdaki çalıştırma, eskimiş alias'lı mesajı bağlantıyı kesmeden atan bir broker'ı gösteriyor. Bu yüzden testiniz asıl önemli sonucu doğrulamalı, yani hatalı mesaj yanlış bir topic altında teslim edilmedi, broker'ın tepkisini ise bilgi olarak kaydetmelidir. Reason code'ları reason code aracı ile çözün. Her durumun çözümü Topic Alias invalid hataları ve MQTT protokol hatası 0x82 yazılarında.

Subscriber tarafını doğrulamak

Subscriber'lar, kendileri tercih etmedikçe alias'ları asla fark etmemelidir. Çevrimiçi MQTT istemcisini açın, testmqtt/alias/# topic'ine abone olun ve betiklerden birini çalıştırın: her mesaj tam topic'i göstermelidir. Topic Alias Maximum bildirmemiş bir subscriber bir gün boş topic alırsa broker hatalıdır. Bu nadir ama ciddi bir hatadır ve bildirilmeye değer.

Alias'lı mesajların tam topic ile gelişini izleyin

Kontrol listesi

  1. Her CONNACK'teki Topic Alias Maximum değerini loglayın ve asla aşmayın.
  2. Önce alias ile birlikte tam topic'i, sonra yalnızca alias'lı yayınları gönderin ve subscriber'ların tam topic gördüğünü doğrulayın.
  3. Yeniden bağlanın ve eskimiş alias'ların kullanılmadığını teyit edin.
  4. Maksimumun üstünde bir alias ve eşlenmemiş bir alias deneyin, broker'ın tepkisini kaydedin.
  5. Alias'ları zorunlu hâle getirmeden önce kendi topic'leriniz için gerçek bayt tasarrufunu ölçün.

Topic alias'lar kısıtlı bağlantılarda ucuz bir kazançtır, diğer yerlerde ise gereksizdir. Müzakereyi ve yeniden bağlanma durumunu test edin; böylece bant genişliği kazandırırken bir cihazın susmasının sebebi olmazlar.

Sıkça sorulan sorular

Topic Alias Maximum'un varsayılan değeri nedir?

0. CONNECT veya CONNACK paketinde Topic Alias Maximum özelliği yoksa alıcı hiçbir alias kabul etmez. Her yön ayrı ayrı müzakere edilir: istemcinin değeri broker'ı, broker'ın değeri istemciyi sınırlar.

Topic alias'lar yeniden bağlanmadan sonra geçerli kalır mı?

Hayır. Alias eşlemeleri, oturum kalıcı olsa bile yalnızca tek bir ağ bağlantısı boyunca var olur. Her yeniden bağlanmadan sonra istemci, alias'ı kullanabilmek için önce tam topic adını yeniden göndermelidir.

Subscriber'lar alias'ı görür mü?

Yalnızca istemişlerse. Alias'lar her atlama için ayrıdır: broker publisher'ın alias'ını tam topic'e çözer ve bir subscriber'a ancak o subscriber kendi Topic Alias Maximum değerini bildirmişse alias kullanır. Çoğu subscriber doğrudan tam topic adını alır.