Temeller

MQTT Last Will and Testament (LWT) Nedir?

MQTT Last Will and Testament nasıl çalışır: broker onu ne zaman gönderir, MQTT 5’te will delay ve kod örnekleriyle retained online/offline presence kalıbı.

Güncellendi · 6 dk okuma

Güvenilmez ağlardaki cihazlar nadiren veda etme fırsatı bulur. Piller biter, Wi-Fi kopar, süreçler çöker. MQTT’nin Last Will and Testament (LWT) özelliği, bir client’ın beklenmedik şekilde ortadan kaybolması durumunda broker’ın onun adına publish edeceği bir mesajı önceden kaydetmesine olanak tanır. MQTT sistemlerinde çevrimiçi durum tespiti (presence) ve alarm üretimi için standart yapı taşıdır.

Last Will nasıl çalışır?

Will mesajı CONNECT paketinde tanımlanır. Normal bir publish ile aynı parçalara sahiptir:

AlanAnlamı
Will TopicBroker’ın publish edeceği yer, ör. acme/sensor-17/status
Will PayloadMesaj gövdesi, ör. offline
Will QoS0, 1 veya 2 — bkz. QoS seviyeleri
Will RetainWill mesajının retained olarak saklanıp saklanmayacağı
Will Properties (MQTT 5)Will Delay Interval, Message Expiry, Content Type, User Properties…

Broker will mesajını oturumla birlikte tutar ve client bağlıyken onunla hiçbir şey yapmaz. Bundan sonra ne olacağı, bağlantının nasıl sona erdiğine bağlıdır.

Will mesajı ne zaman publish edilir?

Broker, ağ bağlantısı normal bir bağlantı kesme olmadan kapandığında will mesajını publish eder; örneğin:

  • broker bir G/Ç hatası veya ağ arızası tespit ettiğinde;
  • client keep-alive süresi içinde iletişim kurmadığında — broker bağlantıyı ölü saymadan önce keep-alive aralığının 1,5 katına kadar bekler;
  • client, DISCONNECT göndermeden TCP/WebSocket bağlantısını kapattığında;
  • broker bir protokol hatası nedeniyle bağlantıyı kapattığında.

Client normal bir DISCONNECT gönderdiğinde will mesajı publish edilmez; düzgün bir kapanış onu siler. MQTT 5 bir istisna ekler: client 0x04 reason code’u (Disconnect with Will Message) ile bağlantıyı düzgünce kapatıp yine de will mesajının gönderilmesini sağlayabilir.

Will Delay Interval (MQTT 5)

MQTT 3.1.1’de will mesajı hemen tetiklenir. Kısa bir ağ kesintisinden sonra hızla yeniden bağlanan cihazlar için bu gürültülüdür: subscriber’lar önce offline, bir saniye sonra da online görür. MQTT 5, Will Delay Interval özelliğini (saniye cinsinden) ekler:

  • Broker will mesajını publish etmeden önce bu gecikme kadar bekler.
  • Client gecikme süresi içinde aynı client ID ile yeniden bağlanırsa will mesajı gönderilmez.
  • Will mesajı, gecikme sona erdiğinde veya oturum bittiğinde (hangisi önce gelirse) publish edilir — yani Session Expiry Interval’dan uzun bir will gecikmesi fiilen onunla sınırlanır.
30 saniye gecikmeli MQTT 5 will mesajı (MQTT.js)
const client = mqtt.connect('wss://broker.emqx.io:8084/mqtt', {
  protocolVersion: 5,
  clientId: 'sensor-17',
  properties: { sessionExpiryInterval: 300 },
  will: {
    topic: 'acme/sensor-17/status',
    payload: 'offline',
    qos: 1,
    retain: true,
    properties: { willDelayInterval: 30 },
  },
});

Presence kalıbı: çevrimiçi/çevrimdışı durumu

LWT’nin en yaygın kullanımı, onu retained mesajlarla birleştirmektir; böylece herhangi bir client, bir cihazın o an çevrimiçi olup olmadığını görebilir:

  1. Bir will ile bağlanın: topic acme/sensor-17/status, payload offline, QoS 1, retain = true.
  2. CONNACK’ten hemen sonra aynı topic’e QoS 1 ve retain = true ile online publish edin. Bu, önceki seferden kalan eskimiş offline mesajının üzerine yazar.
  3. Düzgün kapanışta offline mesajını (retained) kendiniz publish edin, ardından DISCONNECT gönderin. Düzgün bağlantı kesmede will mesajı silindiği için durumu doğru tutan bu açık publish’tir.
  4. Çökme durumunda retained offline will mesajını broker sizin yerinize publish eder.

Panolar daha sonra acme/+/status filtresine abone olur ve retain sayesinde her cihazın güncel durumunu anında alır.

presence.mjs (MQTT.js)
import mqtt from 'mqtt';

const statusTopic = 'acme/sensor-17/status';

const client = mqtt.connect('wss://broker.hivemq.com:8884/mqtt', {
  clientId: 'sensor-17',
  keepalive: 30,
  will: { topic: statusTopic, payload: 'offline', qos: 1, retain: true },
});

client.on('connect', () => {
  client.publish(statusTopic, 'online', { qos: 1, retain: true });
});

process.on('SIGINT', () => {
  client.publish(statusTopic, 'offline', { qos: 1, retain: true }, () => client.end());
});

Sık karşılaşılan tuzaklar

  • Client ID çakışmaları. İkinci bir client aynı client ID ile bağlanırsa broker ilkinin bağlantısını keser — ve onun will mesajını publish eder. Tek bir ID için mücadele eden iki instance, sürekli gidip gelen bir çevrimiçi/çevrimdışı durumu üretir.
  • Her zaman düzgün bağlantı kesen kütüphaneler. Bazı SDK’lar süreç kapanırken DISCONNECT gönderir, bu yüzden will mesajı hiç tetiklenmez. Süreci öldürerek veya ağı keserek test edin.
  • Retain’i unutmak. Retained olmayan bir will mesajını yalnızca o anda abone olan client’lar görür.
  • Yetkilendirme. Will mesajı client’ın yetkileriyle publish edilir. Client’ın will topic’ine publish etme izni yoksa broker bağlantıyı reddedebilir veya will mesajını sessizce düşürebilir. Bkz. MQTT bağlantı hataları.

Komut satırından will ayarlamak

Mosquitto client’ları will seçeneklerini doğrudan kabul eder; bu da hızlı denemeleri kolaylaştırır. Bir terminalde bir subscriber başlatın, ardından ikinci bir client’ı will ile bağlayın ve Ctrl+C ile veya terminali kapatarak sonlandırın:

bash
# terminal 1 — watch the status topic
mosquitto_sub -h test.mosquitto.org -t 'testmqtt/lwt-demo/#' -v

# terminal 2 — connect with a retained will and a 10 s keep-alive
mosquitto_sub -h test.mosquitto.org -t 'testmqtt/lwt-demo/cmd' -k 10 \
  --will-topic 'testmqtt/lwt-demo/status' --will-payload 'offline' \
  --will-qos 1 --will-retain

Sürecin nasıl sonlandığına bağlı olarak client DISCONNECT gönderebilir ya da gönderemeyebilir. Will mesajını görmenin en güvenilir yolu ağı kesmek (örneğin Wi-Fi’yi kapatmak) ve keep-alive süresinin dolmasını beklemektir — LWT’nin tam olarak tasarlandığı arıza senaryosu.

Last Will nasıl test edilir?

  1. Online MQTT client’ın bir sekmesinde testmqtt/lwt-demo/# filtresine abone olun.
  2. İkinci bir sekmede testmqtt/lwt-demo/status üzerinde bir will ve kısa bir keep-alive ile bağlanın.
  3. İkinci sekmeyi bağlantıyı kesmeden kapatın. Keep-alive süresi içinde ilk sekme will mesajını alır.

Online MQTT istemcisinde deneyin

Sıkça sorulan sorular

MQTT Last Will mesajım neden gönderilmiyor?

Broker will mesajını yalnızca client bağlantısı düzgün olmayan şekilde koptuğunda publish eder. Client kütüphaneniz kapanırken bir DISCONNECT paketi gönderiyorsa will mesajı silinir. Keep-alive değerini de kontrol edin: broker ölü bir bağlantıyı fark etmeden önce keep-alive aralığının 1,5 katına kadar bekleyebilir.

Bağlandıktan sonra Last Will mesajını değiştirebilir miyim?

Hayır. Will, CONNECT paketinin bir parçasıdır ve oturum sırasında değiştirilemez. Değiştirmek için bağlantıyı kesip yeni bir will ile yeniden bağlanın.

Last Will mesajı retained olmalı mı?

Presence ve durum topic’leri için evet. Retained bir offline will mesajı, sonradan abone olan client’ların hiçbir şey ya da eski bir online mesajı görmek yerine cihazı yine çevrimdışı olarak görmesini sağlar.