Dokümantasyon ve karşılaştırma tabloları bir broker'ın neler yapabildiğini söyler. Önemli olan, sizin broker'ınızın sizin yapılandırmanız ve sizin kimlik bilgilerinizle gerçekte neye izin verdiğidir. Bunu öğrenmenin en hızlı ve güvenilir yolu broker'ı yoklamaktır: MQTT 5 ile bağlanın, CONNACK özelliklerini okuyun, ardından her özelliği deneyip dönen reason code'lara bakın.
Bu yazı hangi sinyallere bakmanız gerektiğini açıklıyor ve herhangi bir broker için yetenek raporu yazdıran bir Python script'i (paho-mqtt 2.x) veriyor.
Broker'ın CONNACK'te size söyledikleri
Bir MQTT 5 broker'ı sınırlarını CONNACK paketinde duyurur. Önemli kural: bir özellik yalnızca varsayılandan farklıysa gönderilir. RetainAvailable'ın olmaması "bilinmiyor" değil, "evet" demektir.
| CONNACK özelliği | Yoksa varsayılan | Kısıtlıysa ne bozulur |
|---|---|---|
| Maximum QoS | 2 | Bunun üzerinde publish 0x9B QoS not supported alır ve bağlantı kapanır |
| Retain Available | evet | Retained publish'ler 0x9A Retain not supported alır |
| Wildcard Subscription Available | evet | + / # abonelikleri 0xA2 Wildcard Subscriptions not supported alır |
| Shared Subscription Available | evet | $share/... abonelikleri 0x9E Shared Subscriptions not supported alır |
| Subscription Identifiers Available | evet | Identifier içeren abonelikler 0xA1 alır |
| Receive Maximum | 65.535 | Broker'a doğru aynı anda onay bekleyen kaç QoS 1/2 mesajınız olabileceği |
| Maximum Packet Size | sınırsız (protokol maksimumu) | Daha büyük paketler 0x95 Packet too large alır |
| Topic Alias Maximum | 0 (alias kabul edilmez) | Broker'ın izin vermediği bir alias kullanmak 0x94 Topic Alias invalid demektir |
| Server Keep Alive | sizin değeriniz | Broker keep-alive değerinizi geçersiz kılar; istemciniz onun değerini kullanmalıdır |
| Assigned Client Identifier | — | Boş bir client ID ile bağlandığınızda gönderilir |
MQTT 3.1.1'de bunların hiçbiri yoktur. Bir 3.1.1 broker'ı yalnızca bağlantının kabul edilip edilmediğini söyler; geri kalan her şeyi deneyerek test etmeniz gerekir. Bu kodların herhangi birini reason code başvuru aracında arayabilirsiniz.
Yoklama script'i
Aşağıdaki script altı kontrol yapar: protokol sürümleri, CONNACK özellikleri, abonelik başına verilen QoS, wildcard ve shared abonelikler, retained mesajlar ve uçtan uca bir QoS 2 teslimatı. Ortam değişkenleriyle yapılandırın ve önem verdiğiniz her ortamda çalıştırın.
"""Report which MQTT features a broker supports. Requires paho-mqtt >= 2.0."""
import os, threading, time, uuid
import paho.mqtt.client as mqtt
HOST = os.environ.get("MQTT_HOST", "broker.connectmq.com")
PORT = int(os.environ.get("MQTT_PORT", "1883"))
USER, PASS = os.environ.get("MQTT_USER"), os.environ.get("MQTT_PASS")
BASE = f"testmqtt/probe/{uuid.uuid4().hex[:8]}"
DEFAULTS = { # value that applies when the broker omits the property
"MaximumQoS": 2, "RetainAvailable": 1, "WildcardSubscriptionAvailable": 1,
"SharedSubscriptionAvailable": 1, "SubscriptionIdentifierAvailable": 1,
"ReceiveMaximum": 65535, "MaximumPacketSize": "no limit",
"TopicAliasMaximum": 0, "ServerKeepAlive": "client value",
}
def connect(protocol=mqtt.MQTTv5, timeout=10):
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"probe-{uuid.uuid4().hex[:8]}", protocol=protocol)
if USER:
c.username_pw_set(USER, PASS)
if PORT == 8883:
c.tls_set()
done, res = threading.Event(), {}
def on_connect(client, userdata, flags, reason_code, properties):
res.update(rc=reason_code, props=properties)
done.set()
c.on_connect = on_connect
c.connect(HOST, PORT, keepalive=30)
c.loop_start()
if not done.wait(timeout):
c.loop_stop()
raise TimeoutError("no CONNACK")
return c, res["rc"], res["props"]
def close(*clients):
for c in clients:
c.disconnect()
c.loop_stop()
def subscribe(c, topic_filter, qos=2, timeout=5):
done, res = threading.Event(), {}
def on_subscribe(client, userdata, mid, reason_code_list, properties):
res["rc"] = reason_code_list[0]
done.set()
c.on_subscribe = on_subscribe
c.subscribe(topic_filter, qos=qos)
return res["rc"] if done.wait(timeout) else "no SUBACK"
def show(label, value):
print(f" {label:34} {value}")
def main():
print(f"Broker {HOST}:{PORT} (test topics under {BASE})\n")
print("Protocol versions")
for name, proto in (("MQTT 3.1.1", mqtt.MQTTv311), ("MQTT 5", mqtt.MQTTv5)):
try:
c, rc, _ = connect(proto)
show(name, "OK" if not rc.is_failure else f"refused: {rc}")
close(c)
except Exception as e:
show(name, f"FAILED ({e})")
c, rc, props = connect()
if rc.is_failure:
raise SystemExit(f"MQTT 5 connect refused: {rc}")
print("\nCONNACK properties")
for name, default in DEFAULTS.items():
value = getattr(props, name, None)
show(name, value if value is not None else f"{default} (default)")
print("\nSubscriptions (granted QoS or reason code)")
for q in (0, 1, 2):
show(f"QoS {q} subscription", subscribe(c, f"{BASE}/qos/{q}", qos=q))
show("Wildcard filter (+)", subscribe(c, f"{BASE}/+/wild", qos=1))
show("Shared subscription ($share)", subscribe(c, f"$share/probe/{BASE}/shared", qos=1))
print("\nActive tests")
got = {}
received = threading.Event()
def on_message(client, userdata, msg):
got[msg.topic] = msg
received.set()
c.on_message = on_message
# End-to-end QoS 2: publish at 2 to a QoS 2 subscription, check delivered QoS
received.clear()
c.publish(f"{BASE}/qos/2", b"qos2-probe", qos=2)
if received.wait(5):
show("QoS 2 delivery", f"delivered at QoS {got[f'{BASE}/qos/2'].qos}")
else:
show("QoS 2 delivery", "NOT delivered")
# Retained message: publish, then subscribe with a fresh client
topic = f"{BASE}/retain"
try:
c.publish(topic, b"retained-probe", qos=1, retain=True).wait_for_publish(5)
sub, _, _ = connect()
hit = threading.Event()
sub.on_message = lambda client, u, m: m.retain and hit.set()
subscribe(sub, topic, qos=1)
show("Retained message", "OK" if hit.wait(5) else "NOT delivered")
close(sub)
c.publish(topic, b"", qos=1, retain=True).wait_for_publish(5) # clear it
except Exception as e:
show("Retained message", f"FAILED ({e})")
close(c)
if __name__ == "__main__":
main()Kendi bağlantı bilgilerinizle çalıştırın:
pip install "paho-mqtt>=2.0"
MQTT_HOST=broker.connectmq.com MQTT_PORT=8883 \
MQTT_USER="$MQTT_USER" MQTT_PASS="$MQTT_PASS" python probe.pyVerilen QoS değerleri paho ReasonCode nesneleri olarak yazdırılır: Granted QoS 2, broker'ın aboneliği o seviyede kabul ettiği anlamına gelir; 0x80 veya üzeri bir kod (örneğin Not authorized ya da Shared Subscriptions not supported) ise bir reddir. Shared subscription kabul edildiyse ve mesajların gerçekten dağıtılıp dağıtılmadığını öğrenmek istiyorsanız shared subscription testini kullanın.
Raporu okumak
Tipik bulgular ve yapılması gerekenler:
- MQTT 5 reddedildi, 3.1.1 OK — eski bir broker sürümü veya 3.1.1 ile sınırlı bir listener. MQTT 5 istemcinizin fallback yapması ya da broker'ın güncellenmesi gerekir. Bkz. MQTT 5 ve 3.1.1 karşılaştırması.
- MaximumQoS 1 — bulut IoT servislerinde ve throughput için yapılandırılmış bazı broker'larda yaygındır. QoS 2 ile publish istemcinizi
0x9Bile düşürür; QoS 1 ve idempotent handler'larla tasarlayın. - Abonelik istenenden düşük bir QoS ile verildi — bu kurala uygundur. Broker reddetmek yerine seviyeyi düşürür ve mesajlar verilen seviyede gelir. İstemcinizde yalnızca istenen QoS'u değil, verilen QoS'u da kontrol edin.
- RetainAvailable 0 veya retained mesaj teslim edilmedi — retained duruma (subscribe anındaki son değer) güvenen cihazlar bozuk görünür. Ayrıntılar için retain desteklenmiyor yazısına bakın.
- TopicAliasMaximum 0 — broker istemcilerden topic alias kabul etmez; alias'ları otomatik atayan kütüphanelerde bu özelliğin kapatılması gerekir.
- MaximumPacketSize ayarlanmış — en büyük payload'ınızı topic ve özelliklerle birlikte paket boyutu hesaplayıcısı ile karşılaştırın.
- Bir abonelikte Not authorized — eksik bir özellik değil, bir ACL'dir. Yoklamayı cihazlarınızın kullandığı kullanıcıyla çalıştırın ve MQTT ACL izinlerini test etme yazısına bakın.
Aynı kontrol JavaScript ile
MQTT.js 5'te CONNACK özellikleri connect olayına geçirilen pakette bulunur:
import mqtt from 'mqtt';
const client = mqtt.connect('mqtts://broker.connectmq.com:8883', {
protocolVersion: 5,
username: process.env.MQTT_USER,
password: process.env.MQTT_PASS,
});
client.on('connect', (connack) => {
// Absent keys mean the spec default applies
console.log(connack.properties ?? '(no properties: all defaults)');
client.subscribe('$share/probe/testmqtt/probe/js', { qos: 2 }, (err, granted) => {
console.log(err ?? granted); // granted[0].qos is the granted QoS or a reason code
client.end();
});
});
client.on('error', (err) => console.error('connect failed:', err.message));Buradaki özellik adları camelCase'tir: maximumQoS, retainAvailable, maximumPacketSize, topicAliasMaximum, wildcardSubscriptionAvailable, sharedSubscriptionAvailable, subscriptionIdentifiersAvailable, receiveMaximum ve serverKeepAlive.
Kod yok mu? mqtt test kullanın
HiveMQ MQTT CLI'da bu yoklama hazır gelir: mqtt test -h broker.connectmq.com, deneyerek ölçülen maksimum topic uzunluğu ve payload boyutu dahil MQTT 3 ve MQTT 5 yeteneklerini yazdırır. Çıktının açıklaması mqtt-cli rehberinde. Hızlı bir manuel kontrol için online MQTT istemcisi ile MQTT 5 kullanarak bağlanın ve bir retained publish ile bir $share/ aboneliği deneyin.
Pipeline'ınızın parçası yapın
Yetenekler sessizce değişir: bir broker güncellemesi, yeni bir listener, yönetilen bir serviste farklı bir plan. Yoklama çıktısını repository'nize kaydedin ve CI'da karşılaştırın:
python probe.py | sed -E 's#testmqtt/probe/[0-9a-f]+#testmqtt/probe/X#' > capabilities.txt
git diff --exit-code capabilities.txtsed, rastgele topic sonekini kaldırır; böylece diff'te yalnızca gerçek değişiklikler görünür. Bunu MQTT broker nasıl test edilir yazısındaki kontrollerle birleştirin; eksik bir özelliği sahadaki bir cihazdan önce siz öğrenin.
Yoklama topic'lerini tarayıcıda izleyin
Beş dakikalık bir yoklama, "rastgele" bağlantı kopmalarını ayıklamakla geçen bir öğleden sonradan iyidir. CONNACK'i okuyun, güvendiğiniz her özelliği deneyin ve raporu sürüm kontrolünde tutun; böylece broker'lar ve ortamlar arasındaki farklar asla sürpriz olmaz.
Sıkça sorulan sorular
Bir broker'ın MQTT 5 destekleyip desteklemediğini nasıl anlarım?
Protokol sürümü 5 ile bağlanın. Destekleyen bir broker genellikle özellikler içeren bir MQTT 5 CONNACK ile yanıt verir. Desteklemeyen bir broker 'unacceptable protocol version' (3.1.1'de 0x01, MQTT 5'te 0x84) döndürür veya bağlantıyı kapatır.
CONNACK'te bir özellik yoksa o özellik desteklenmiyor mu demektir?
Hayır, tam tersi. MQTT 5'te eksik bir özellik varsayılan değerin geçerli olduğu anlamına gelir: retain, wildcard'lar, shared subscription'lar ve subscription identifier'lar kullanılabilir, maksimum QoS 2'dir ve receive maximum 65.535'tir. Broker'lar yalnızca bu varsayılanları kısıtlayan veya değiştiren özellikleri gönderir.
Bir broker bir özelliği destekleyip benim istemcime yasaklayabilir mi?
Evet. ACL'ler, listener bazlı ayarlar ve yönetilen servislerdeki planlar belirli kullanıcılar için QoS, retain, wildcard veya topic'leri kısıtlayabilir. Bu yüzden yoklama script'i cihazlarınızla aynı kimlik bilgileri ve aynı port ile çalıştırılmalıdır.


