Temeller

MQTT Topic’leri ve Wildcard’lar: Tasarım Rehberi ve En İyi Uygulamalar

MQTT topic’leri ve wildcard’lar: topic seviyeleri, + ve # joker karakterleri, $SYS topic’leri, paylaşımlı abonelikler ve topic hiyerarşisi tasarım ipuçları.

Güncellendi · 7 dk okuma

MQTT’de publisher’ları ve subscriber’ları birbirine bağlayan tek şey topic’tir. Yapılandırılacak kuyruklar veya exchange’ler yoktur — broker her mesajın topic’ini tüm abonelik filtreleriyle karşılaştırır. Bu da topic tasarımını sisteminizin omurgası yapar: client’ların nelere abone olabileceğini, yetkilerin nasıl ifade edileceğini ve sonradan yeni tüketiciler eklemenin ne kadar kolay olacağını belirler.

Topic temelleri

Bir topic adı, eğik çizgiyle (slash) ayrılmış seviyelerden oluşan bir UTF-8 dizesidir:

text
building-a/floor-3/room-12/temperature
vehicles/truck-0042/gps
acme/devices/sensor-17/status
  • Topic’ler büyük/küçük harfe duyarlıdır. Home/Kitchen ve home/kitchen farklı topic’lerdir.
  • Kayıt gerekmez. Bir topic, biri ona publish ettiği anda var olur.
  • Her karakter önemlidir. Baştaki bir slash boş bir ilk seviye oluşturur; yani /home/kitchen ile home/kitchen aynı değildir. Boşluklar geçerlidir ama bitmek bilmeyen karışıklıklara yol açar.
  • Boyut. Topic adları en az bir karakter, en fazla 65.535 bayt olmalı ve null karakter içermemelidir.

Wildcard’lar (joker karakterler): + ve #

Subscriber’lar iki wildcard içerebilen topic filtreleri kullanır. Publisher’lar ise her zaman somut topic adları kullanır — bir PUBLISH içinde wildcard kullanmak protokol ihlalidir.

Tek seviyeli wildcard: +

+ tam olarak bir seviyeyle eşleşir. Bir seviyenin tamamını kaplamalıdır (sensor+ geçersizdir), ancak her yerde ve birden fazla kez kullanılabilir.

FiltreEşleşirEşleşmez
home/+/temperaturehome/kitchen/temperaturehome/kitchen/oven/temperature
+/+/statusacme/sensor-17/statusacme/status
home/+home/kitchenhome, home/kitchen/light

Çok seviyeli wildcard: #

# sıfır dahil herhangi sayıda seviyeyle eşleşir ve filtrenin kendi seviyesinde duran son karakteri olmalıdır. home/#; home/kitchen, home/kitchen/light/state ve üst seviye olan home ile de eşleşir. home/#/light veya home# gibi filtreler geçersizdir.

Tek başına #, broker’daki tüm topic’lere ($ topic’leri hariç) abone olur. Kendi özel broker’ınızda hata ayıklamak için kullanışlıdır, ancak genel bir broker’da sizi başkalarının trafiğine boğar.

$SYS ve diğer $ topic’leri

$ ile başlayan topic’ler broker’a ayrılmıştır. En yaygını $SYS/’dur; birçok broker (Mosquitto, EMQX ve diğerleri) burada bağlı client sayısı, mesaj hızları ve çalışma süresi gibi istatistikler yayınlar. Topic’lerin tam listesi broker’a özgüdür — spesifikasyon yalnızca öneki ayırır.

İlk seviyedeki wildcard’lar $ topic’leriyle eşleşmez: # ve +/monitor hiçbir zaman $SYS/... mesajlarını teslim etmez. Açıkça abone olun:

bash
mosquitto_sub -h test.mosquitto.org -t '$SYS/broker/clients/connected' -v

MQTT 5 bir ayrılmış önek daha ekler: shared subscription’lar (paylaşımlı abonelikler) $share/<group>/<filter> biçimini kullanır. Aynı gruptaki tüm subscriber’lar akışı paylaşır ve her mesaj yalnızca bir üyeye gider — tüketiciler arasında yük dengelemenin basit bir yolu. Topic alias gibi diğer MQTT 5 yenilikleri için MQTT 5 ve 3.1.1 yazısına bakın.

Topic hiyerarşisi tasarlamak

İyi bir hiyerarşi genelden özele doğru ilerler; böylece sondaki wildcard’lar anlamlı grupları seçer. Yaygın bir kalıp şudur:

text
<org-or-app>/<site>/<device-type>/<device-id>/<measurement-or-channel>

acme/berlin/thermostat/th-0193/temperature
acme/berlin/thermostat/th-0193/setpoint/set
acme/berlin/thermostat/th-0193/status

Bu düzenle:

  • acme/berlin/# bir lokasyon panosuna Berlin’deki her şeyi verir.
  • acme/+/thermostat/+/temperature bir analitik servisine tüm termostat ölçümlerini verir.
  • acme/berlin/thermostat/th-0193/# tek bir cihazın tüm akışını verir.

En iyi uygulamalar

  1. Slash ile başlamayın. Gereksiz, boş bir seviye ekler.
  2. Küçük harf, ASCII ve tire kullanın. Boşluklardan ve karışık büyük/küçük harften kaçının; ince eşleşme hatalarına yol açarlar.
  3. Cihaz veya client ID’sini topic’e koyun. Client bazında erişim kontrolünü kolaylaştırır (birçok broker, ACL pattern’lerinde client ID’yi veya kullanıcı adını yerine koyabilir).
  4. Veriyi, komutları ve durumu ayırın. Örneğin telemetri için .../temperature, komutlar için .../setpoint/set, retained durum veya Last Will ile çevrimiçi/çevrimdışı bilgisi için .../status.
  5. Topic’leri kısa ama açıklayıcı tutun. Topic her mesajla birlikte gönderilir (MQTT 5 topic alias kullanmıyorsanız), bu yüzden çok uzun adlar kısıtlı bağlantılarda bant genişliğine mal olur.
  6. Veriyi topic’e kodlamayın. Değerler payload’a aittir; her değer için bir topic, sınırsız sayıda topic’e ve bir sürü retained mesaja yol açar.
  7. Değişebilecekse şemanızı versiyonlayın. v1/ gibi bir önek, geçiş sırasında eski ve yeni cihazların bir arada çalışmasını sağlar.
  8. Üretimde geniş aboneliklerden kaçının. Bir backend servisinde #’e abone olmak, broker’daki her mesajı o servisin sorunu haline getirir.

Sık yapılan topic hataları

  • a/+ filtresinin a ile eşleşmesini beklemek. Eşleşmez — + bir seviyenin var olmasını gerektirir. Üst seviyeyi de istiyorsanız a/# kullanın.
  • Sondaki slash’ler. home/kitchen/ boş bir son seviyeye sahiptir ve home/kitchen’dan farklı bir topic’tir.
  • Çakışan abonelikler. Bir client hem home/# hem de home/+/temperature filtresine abone olursa spesifikasyon, broker’ın tek bir kopya ya da eşleşen her abonelik için bir kopya teslim etmesine izin verir; bu yüzden bazı broker’lar size kopya mesajlar gönderir. Mümkün olduğunca abonelikleri ayrık tutun.
  • ID formatlarını karıştırmak. Bazı cihazlar Sensor_17, bazıları sensor-17 olarak publish ediyorsa her filtre ve ACL kuralı ikisini de ele almak zorunda kalır. ID’leri provisioning sırasında normalleştirin.
  • Topic’leri veritabanı gibi kullanmak. Broker’lar sorgulama için değil, yönlendirme için optimize edilmiştir. Geçmiş veriye ihtiyacınız varsa bir tüketicinin abone olup mesajları bir veritabanına yazmasını sağlayın.

Topic’ler ve erişim kontrolü

Broker’lar publish ve subscribe işlemlerini topic bazında yetkilendirir; dolayısıyla hiyerarşiniz aynı zamanda yetki modelinizdir. Her cihaz yalnızca acme/<site>/<type>/<device-id>/ altına yazıyorsa ona tam olarak bu alt ağacı verebilir, başka hiçbir şeyi vermeyebilirsiniz. Topic’ler düz veya tutarsızsa sıkı kurallar yazmak imkânsızlaşır ve ekipler sonunda herkese # yetkisi verir.

Kendiniz deneyin

Online MQTT client’ı açın, testmqtt/demo/+/temperature filtresine abone olun ve testmqtt/demo/kitchen/temperature ile testmqtt/demo/kitchen/oven/temperature topic’lerine publish edin. Yalnızca ilk mesaj gelir — tam da + kuralının öngördüğü gibi.

Online MQTT istemcisinde deneyin

Sıkça sorulan sorular

MQTT’de + ile # arasındaki fark nedir?

+ wildcard’ı tam olarak bir topic seviyesiyle eşleşir ve filtrenin herhangi bir yerinde kullanılabilir. # wildcard’ı ise sıfır dahil herhangi sayıda seviyeyle eşleşir ve filtrenin son karakteri olmalıdır.

Wildcard içeren bir topic’e publish edebilir miyim?

Hayır. Wildcard’lar yalnızca abonelik filtrelerinde geçerlidir. Topic adında + veya # bulunan bir PUBLISH protokol hatasıdır ve broker bağlantıyı kapatır.

# filtresine abone olmak $SYS topic’lerini de kapsar mı?

Hayır. Wildcard ile başlayan filtreler $ ile başlayan topic’lerle eşleşmez. Broker istatistiklerini almak için açıkça abone olmanız gerekir, örneğin $SYS/# filtresine.