MQTT Last Will and Testament (LWT), artık kendisi konuşamayan bir istemci adına broker'ın konuşmasını sağlayan özelliktir. Bir cihaz bağlanırken bir "will" (vasiyet) mesajı kaydeder ve cihaz düzgün bir bağlantı kesme işlemi yapmadan ortadan kaybolursa broker bu mesajı publish eder. Bu makalenin sonunda her will alanını, onu tetikleyen kesin koşulları ve canlı bir broker'a bağlı bir istemciyi sonlandırarak bunu kendiniz nasıl test edeceğinizi öğrenmiş olacaksınız.
MQTT Neden Bir Last Will'e İhtiyaç Duyar?
MQTT güvenilmez ağlar için tasarlanmıştır. Cihazların gücü kesilir, firmware kilitlenir, hücresel bağlantılar dakikalarca kopar. Saf bir publish/subscribe sisteminde publisher ve subscriber hiçbir zaman doğrudan konuşmaz; dolayısıyla bir insan eskimiş bir dashboard'a bakana kadar kimse bir sensörün sessizleştiğini fark etmez.
MQTT broker, her bağlantıyı gören tek taraftır. LWT bu konumu bir özelliğe dönüştürür: İstemci broker'a önceden "ortadan kaybolursam bunu benim için publish et" der. Subscriber'lar da arızadan, zaten izledikleri aynı topic'ler üzerinden haberdar olur.
MQTT Last Will and Testament Alanları
Will, CONNECT paketinin içinde ayarlanır; bu yüzden istemci bağlanmadan önce yapılandırılmalıdır. Bir oturum sırasında değiştirilemez; değiştirmek için yeniden bağlanın.
| Alan | Amaç | Tipik değer |
|---|---|---|
| Will topic | Broker'ın will'i publish ettiği yer | site/line1/pump-07/status |
| Will payload | Mesaj gövdesi | offline veya {"state":"offline"} |
| Will QoS | Will için teslim garantisi | 1 |
| Will retain | Will'in retained değer olup olmayacağı | true |
| Will delay interval (MQTT 5) | Publish etmeden önce beklenecek saniye | 0 ile birkaç saniye arası |
| Will property'leri (MQTT 5) | Message expiry, content type, user property'ler | İsteğe bağlı |
Production kurulumlarının çoğu QoS 1 ve retain true kullanır. Durumu sonradan bağlanan istemciler için yararlı kılan retain'dir; o olmadan arızadan sonra açılan bir dashboard cihazın kapalı olduğunu hiçbir zaman öğrenemez. Retained davranışı MQTT retained mesajlar yazısında ayrıntılı olarak açıklanıyor.
Broker Will'i Ne Zaman Publish Eder?
Broker, ağ bağlantısı bir DISCONNECT paketi olmadan kapandığında will'i publish eder. Pratikte bu şunları kapsar:
- TCP bağlantısı istemcinin işletim sistemi tarafından kapatılır veya sıfırlanır; örneğin sonlandırılmış bir süreç.
- Keepalive zamanlayıcısının süresi dolar. Broker, istemciyi ölü ilan etmeden önce hiç paket gelmeden yaklaşık 1,5 keepalive aralığı kadar bekler.
- İstemci protokolü ihlal eder ve broker bağlantıyı kapatır.
- Broker'ın bir I/O hatası aracılığıyla tespit ettiği bir ağ arızası.
Şu durumlarda will'i publish etmez:
- İstemci normal bir DISCONNECT gönderir. Will atılır.
- MQTT 5'te istemci, will delay interval dolmadan yeniden bağlanır ve oturumunu sürdürür.
Bu ikinci kural önemlidir: Düzgün bir kapanış will üretmez. Düzgün kapanışta da "offline" istiyorsanız, bağlantıyı kesmeden önce bunu kendiniz publish edin. MQTT 5 ayrıca bir istemcinin, broker'dan will'i yine de publish etmesini istemek için 0x04 reason code'lu (disconnect with will message) bir DISCONNECT göndermesine izin verir.
Bir İstemciyi Sonlandırarak LWT'yi Test Etmek
Sezgi kazanmanın en hızlı yolu bir will'in tetiklendiğini izlemektir. Benzersiz bir topic önekiyle broker.connectmq.com adresindeki herkese açık MQTT test broker'ını kullanıyoruz.
Terminal 1, izleyici:
mosquitto_sub -h broker.connectmq.com -p 1883 -i lwt-watch-q81m \
-t 'connectmq/demo/q81m/#' -v
Terminal 2, "cihaz". Retained bir will kaydeder, 10 saniyelik bir keepalive kullanır ve sürecin çalışmaya devam etmesi için subscribe durumda kalır:
mosquitto_sub -h broker.connectmq.com -p 1883 -i lwt-device-q81m -k 10 \
--will-topic connectmq/demo/q81m/device1/status \
--will-payload offline --will-qos 1 --will-retain \
-t connectmq/demo/q81m/device1/cmd
Terminal 3, retained bir birth (doğum) mesajıyla cihazı çevrimiçi olarak duyurun:
mosquitto_pub -h broker.connectmq.com -p 1883 -i lwt-birth-q81m \
-t connectmq/demo/q81m/device1/status -m online -q 1 -r
Şimdi cihazı aniden sonlandırın. Linux veya macOS'ta:
pkill -9 -f lwt-device-q81m
Terminal 1 neredeyse hemen connectmq/demo/q81m/device1/status offline yazdırır, çünkü işletim sistemi soketi kapatmıştır ve broker bağlantının DISCONNECT olmadan koptuğunu görmüştür. Bunun yerine ağ kablosunu çekerseniz veya bir dizüstü bilgisayarı uyku moduna alırsanız will ancak keepalive penceresi geçtikten sonra, -k 10 ile yaklaşık 15 saniye sonra gelir.
Bir deney daha yapın: Cihaz sürecini yeniden başlatın ve Ctrl+C ile durdurun. Mosquitto araçları Ctrl+C'de düzgün bir DISCONNECT gönderir; bu yüzden hiçbir will publish edilmez ve retained durum neyse öyle kalır. Kapanışta açık bir offline publish ile kapattığınız boşluk budur.
paho-mqtt ile Python'da LWT
İşte paho-mqtt 2.x kullanan eksiksiz bir cihaz iskeleti. Bağlanmadan önce will'i ayarlar, on_connect içinde retained bir birth mesajı publish eder (böylece her yeniden bağlanmadan sonra tekrarlanır) ve düzgün çıkışta "offline" publish eder:
import signal
import sys
import time
import paho.mqtt.client as mqtt
BROKER = "broker.connectmq.com"
CLIENT_ID = "lwt-py-device-q81m"
STATUS = "connectmq/demo/q81m/device2/status"
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.will_set(STATUS, payload="offline", qos=1, retain=True)
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print("connect failed:", reason_code)
return
client.publish(STATUS, "online", qos=1, retain=True)
print("online")
def shutdown(signum, frame):
client.publish(STATUS, "offline", qos=1, retain=True).wait_for_publish(timeout=5)
client.disconnect()
client.loop_stop()
sys.exit(0)
client.on_connect = on_connect
signal.signal(signal.SIGINT, shutdown)
signal.signal(signal.SIGTERM, shutdown)
client.connect(BROKER, 1883, keepalive=15)
client.loop_start()
while True:
time.sleep(1)
Çalıştırın, izleyici terminalde "online" yazısının belirdiğini görün; ardından broker'ın publish ettiği will'i görmek için kill -9 ile sonlandırın ya da betiğin kendi offline mesajını görmek için Ctrl+C'ye basın.
Güvenilir Çevrimdışı Tespiti İçin Tasarım İpuçları
Makul bir keepalive seçin. Keepalive, sessiz arızalar için en kötü durumdaki tespit süresini belirler. Şebekeden beslenen cihazlar için 15 ila 60 saniye yaygındır. Çok kısa değerler pile ve bant genişliğine mal olur; çok uzun değerler ise alarmları geciktirir. MQTT keep alive aralığı rehberimiz bu ödünleşimleri ele alıyor.
LWT'yi her zaman bir birth mesajıyla eşleştirin. Will yalnızca "offline" der. Yeniden bağlandıktan sonra bir şeyin tekrar "online" demesi gerekir ve bunun retained will'in üzerine yazması için retained olması şarttır.
Her ikisi için de aynı topic'i ve retain bayrağını kullanın. Will retained olup birth retained değilse, yeni subscriber'lar sonsuza kadar "offline" görür.
Tekrarlanan client ID'lere dikkat edin. İki cihaz aynı client ID'yi paylaşırsa, biri bağlandığında broker diğerinin bağlantısını keser ve bir döngü içinde birbirlerini düşürürler. Durum online ile offline arasında gidip gelir. Her client ID'yi benzersiz yapın.
MQTT 5'te bir will gecikmesi düşünün. Kısa bir gecikme, bir ağ aksaklığından sonra hızla yeniden bağlanan bir cihazda anlık bir "offline" görünmesini önler. Ayrıntılar için MQTT will delay interval yazısına bakın.
JSON payload'lara bağlam ekleyin. {"state":"offline","reason":"lwt"} gibi bir payload, tüketicilerin bir çökmeyi planlı bir kapanıştan ayırt etmesini sağlar.
ConnectMQ'da Last Will and Testament
ConnectMQ, retained will'ler dahil olmak üzere hem MQTT 3.1.1 hem de 5.0 bağlantılarında LWT'yi destekler. Production broker'da portaldan aldığınız kimlik bilgileriyle (YOUR_USERNAME, YOUR_PASSWORD, YOUR_CLIENT_ID) 8883 portu üzerinden TLS ile bağlanırsınız ve will, yukarıdaki örneklerde olduğu gibi çalışır. ConnectMQ'da client ID'ler verilen kimlik bilgilerine bağlı olduğundan, tekrarlanan ID kaynaklı gidip gelme sorunundan kaçınmak daha kolaydır.
LWT'ye ek olarak broker tarafında görünürlük için ConnectMQ, bağlantı durumunu $SYS/broker/connection/{clientId}/state üzerinden de sunar; bu, her cihazın will'ini doğru yapılandırmasına bağımlı olmaması gereken izleme araçları için kullanışlıdır. Bunu nerede barındıracağınıza karar veriyorsanız seçenekleri barındırılan MQTT broker genel bakışımızda karşılaştırın; protokol temelleri için ise kapsamlı MQTT eğitimine bakın.
ConnectMQ ile Başlayın
app.connectmq.com adresinde kaydolun ve kredi kartı gerekmeden ücretsiz Serverless planda bir broker oluşturun. Cihazlarınızı retained bir Last Will ve bir birth mesajıyla ona yönlendirin; ilk günden itibaren güvenilir bir çevrimiçi/çevrimdışı durum bilgisine sahip olun.
Sık Sorulan Sorular
Bir istemci normal şekilde bağlantıyı kestiğinde Last Will publish edilir mi?
Hayır. Normal bir DISCONNECT, broker'a will'i atmasını söyler. Planlı kapanışlar için bir offline mesajına ihtiyacınız varsa, bağlantıyı kesmeden önce kendiniz publish edin.
Broker'ın will'i publish etmesi ne kadar sürer?
Soket kapanırsa neredeyse anında. Cihaz sessizce ortadan kaybolursa broker, yaklaşık 1,5 keepalive aralığı ve varsa MQTT 5 will delay interval kadar bekler.
Will mesajı retained olmalı mı?
Genellikle evet. Retained bir will, arızadan sonra bağlanan istemcilerin de cihazı çevrimdışı olarak görmesini sağlar.
Bağlandıktan sonra will'i değiştirebilir miyim?
Hayır. Will, CONNECT paketinin bir parçasıdır. Değiştirmek için bağlantıyı kesin ve yeni will ayarlarıyla yeniden bağlanın.



