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:
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/Kitchenvehome/kitchenfarklı 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/kitchenilehome/kitchenaynı 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.
| Filtre | Eşleşir | Eşleşmez |
|---|---|---|
home/+/temperature | home/kitchen/temperature | home/kitchen/oven/temperature |
+/+/status | acme/sensor-17/status | acme/status |
home/+ | home/kitchen | home, 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:
mosquitto_sub -h test.mosquitto.org -t '$SYS/broker/clients/connected' -vMQTT 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:
<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/statusBu düzenle:
acme/berlin/#bir lokasyon panosuna Berlin’deki her şeyi verir.acme/+/thermostat/+/temperaturebir 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
- Slash ile başlamayın. Gereksiz, boş bir seviye ekler.
- 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.
- 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).
- 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. - 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.
- 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.
- 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. - Ü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/+filtresininaile eşleşmesini beklemek. Eşleşmez —+bir seviyenin var olmasını gerektirir. Üst seviyeyi de istiyorsanıza/#kullanın.- Sondaki slash’ler.
home/kitchen/boş bir son seviyeye sahiptir vehome/kitchen’dan farklı bir topic’tir. - Çakışan abonelikler. Bir client hem
home/#hem dehome/+/temperaturefiltresine 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-17olarak 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.