Temeller

MQTT Keep Alive: PINGREQ, Zaman Aşımları ve Ayarlama

MQTT keep alive nasıl çalışır: 1,5× zaman aşımı kuralı, PINGREQ ve PINGRESP, MQTT 5 Server Keep Alive, NAT ve mobil ağ tuzakları ve doğru aralığın seçimi.

Güncellendi · 7 dk okuma

TCP bağlantıları sessizce ölebilir. Bir router yeniden başlar, bir cep telefonu baz istasyonu değiştirir, bir NAT tablosu kaydının süresi dolar — ve iki taraf da düzgün bir kapanış almaz. MQTT’nin keep alive mekanizması, hem client’ın hem de broker’ın ölü bir bağlantıyı öngörülebilir bir süre içinde fark etmesi ve bu olduğunda broker’ın client’ın Last Will mesajını publish edebilmesi için vardır. Bu yazı, keep alive’ın MQTT 3.1.1 ve 5’te tam olarak nasıl çalıştığını ve ağınıza uygun bir değeri nasıl seçeceğinizi açıklıyor.

Keep alive aralığı nedir?

Keep alive, client’ın CONNECT paketinde gönderdiği, saniye cinsinden 16 bitlik bir değerdir. Bir sözdür: “Bundan daha uzun süre asla sessiz kalmayacağım.” Maksimum değer 65535 saniyedir (18 saatten biraz fazla); 0 ise mekanizmayı tamamen devre dışı bırakır.

Kritik nokta şu: zamanlayıcı yalnızca ping’lerle değil, herhangi bir kontrol paketiyle ilgilidir. 60 saniyelik keep alive ile her 10 saniyede bir sensör ölçümü publish eden bir client’ın hiç ping göndermesine gerek yoktur, çünkü PUBLISH paketleri zaten hayatta olduğunu kanıtlar. Ping’ler yalnızca client’ın söyleyecek başka bir şeyi olmadığında gönderilir.

PINGREQ ve PINGRESP

Keep alive süresi client hiçbir şey göndermeden dolmak üzereyken client bir PINGREQ gönderir. Broker bir PINGRESP ile yanıt vermek zorundadır. İki paket de çok küçüktür: variable header ve payload olmadan yalnızca 2 baytlık bir fixed header.

PaketYönHattaki baytlarAmaç
PINGREQClient → broker0xC0 0x00Client’ın hayatta olduğunu kanıtlar; broker’ın hayatta olup olmadığını sorar
PINGRESPBroker → client0xD0 0x00Broker’ın ve client’a dönüş yolunun çalıştığını kanıtlar

İki baytlık MQTT hikâyenin tamamı değildir — TCP/IP, TLS kayıtları ve tarayıcılar için WebSocket çerçeveleme her ping’e ek yük bindirir. Bir hücresel veri paketini boyutlandırıyorsanız MQTT paket boyutu hesaplayıcı her paketin MQTT kısmını tahmin etmenize yardımcı olur; aktarım katmanı ek yükünü bunun üzerine ekleyebilirsiniz.

1,5× kuralı: bağlantı ne zaman ölü sayılır?

İki taraf keep alive’ı farklı şekilde kullanır:

  • Broker tarafı — broker, keep alive süresinin bir buçuk katı içinde client’tan hiçbir kontrol paketi almazsa ağ arızalanmış gibi bağlantıyı kapatmak zorundadır. 60 saniyelik bir keep alive ile bu, 90 saniyelik bir sessizlik demektir.
  • Client tarafı — client bir PINGREQ gönderir ve makul bir süre içinde PINGRESP almazsa bağlantıyı kendisi kapatmalıdır. Kütüphaneler genellikle bir sonraki keep alive tikine kadar gelmeyen ping yanıtını hata sayar ve yeniden bağlanmaya başlar.

Broker keep alive zaman aşımını anormal bir bağlantı kesilmesi olarak ele aldığı için client’ın Last Will mesajı publish edilir. Klasik “cihaz çevrimdışı” kalıbını çalıştıran şey budur: devices/42/status üzerinde offline içerikli retained bir will ayarlayın; broker, cihaz ortadan kaybolduktan en fazla 1,5 keep alive süresi sonra arızayı sizin adınıza duyurur.

MQTT 5’te Server Keep Alive

MQTT 3.1.1’de keep alive’a client karar verir ve broker bunu kabul etmek (ya da bağlantıyı reddetmek) zorundadır. MQTT 5, CONNACK paketine bir Server Keep Alive özelliği ekler. Broker bunu gönderirse client, istediği değer yerine broker’ın değerini kullanmak zorundadır. Broker’lar bunu, client’ların 0 veya saatlerce süren bir keep alive talep ederek ölü bağlantıların birikmesine yol açmasını önlemek için kullanır.

MQTT 5 hatayı da açık hale getirir: broker bağlantıyı kapatmadan önce 0x8D (Keep Alive timeout) reason code’lu bir DISCONNECT gönderebilir. Bu kodu ve diğer tüm kodları MQTT reason code başvuru kaynağında bulabilirsiniz. Diğer protokol farkları için MQTT 5 ve 3.1.1 yazısına bakın.

Broker’lar genellikle sunucu tarafında da sınırlar uygular. Örneğin Mosquitto’nun bir max_keepalive seçeneği vardır: MQTT 5 client’ları sınırlandırılmış değeri Server Keep Alive aracılığıyla alırken daha fazlasını isteyen MQTT 3.1.1 client’ları reddedilebilir.

Yaygın client’larda keep alive ayarlamak

Çoğu kütüphane varsayılan olarak 60 saniye kullanır. Değiştirmek için:

mosquitto_sub
# -k sets the keep alive in seconds
mosquitto_sub -h broker.hivemq.com -t 'testmqtt/ka-demo/#' -k 30 -v
MQTT.js
import mqtt from 'mqtt';

const client = mqtt.connect('wss://broker.hivemq.com:8884/mqtt', {
  keepalive: 30,        // seconds; 0 disables
  reconnectPeriod: 2000 // ms between reconnect attempts
});
Paho MQTT (Python)
import paho.mqtt.client as mqtt

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.connect("broker.hivemq.com", 1883, keepalive=30)
client.loop_forever()

Kendi diliniz için tam bir kod parçası mı istiyorsunuz? MQTT kod oluşturucu, keep alive’ı önceden ayarlanmış bağlantı kodu üretir. Davranışı canlı izlemek için online MQTT client ile kısa bir keep alive kullanarak bağlanın ve boşta bırakın.

Online MQTT istemcisinde deneyin

NAT, firewall’lar ve mobil ağlar

Keep alive’ın spesifikasyonda bahsedilmeyen ikinci bir görevi daha vardır: aradaki ağ cihazlarını memnun tutmak. NAT ağ geçitleri, mobil ağlardaki carrier-grade NAT, load balancer’lar ve stateful firewall’lar, boşta kalan TCP akışlarını bir zaman aşımından sonra düşürür. Eşleme kaybolduğunda client hâlâ bağlı olduğunu sanır, ancak gönderdiği hiçbir şey broker’a, broker’ın gönderdiği hiçbir şey de client’a ulaşmaz.

  • Yol üzerindeki en kısa boşta kalma zaman aşımının altında kalın. Bulut load balancer’ları ve mobil operatörler genellikle birkaç dakikalık, bazen daha kısa zaman aşımları kullanır. Bunun rahatça altında bir keep alive eşlemeyi canlı tutar.
  • TCP keepalive’a güvenmeyin. İşletim sistemlerinin TCP keepalive varsayılanları genellikle saatlerle ölçülür; bir MQTT oturumunu korumak için çok yavaştır.
  • Pil ile dengeleyin. Her ping radyoyu uyandırır. Pille çalışan hücresel cihazlarda daha uzun aralıklar ile bir kalıcı oturumun (kaçırılan mesajlar kuyruğa alınsın diye) birleşimi çoğu zaman daha iyi bir dengedir.
  • WebSocket’ler istisna değildir. Proxy’lerin arkasındaki tarayıcı client’ları aynı zaman aşımlarıyla karşılaşır; MQTT keep alive, WebSocket üzerinden MQTT’de de aynı şekilde çalışır.

Keep alive değeri nasıl seçilir?

SenaryoÖnerilen keep aliveNeden
Kararlı ağlardaki panolar ve backend servisleri30–60 snKütüphane varsayılanı, düşük ek yük, yaklaşık bir dakikada tespit
“Offline” durumunun hızlı görünmesi gereken cihazlar10–20 snWill mesajı kabaca 15–30 sn içinde tetiklenir
Hücresel / yoğun NAT içeren ağlarYol üzerindeki en kısa boşta kalma zaman aşımının altındaSessiz yarı açık bağlantıları önler
Pille çalışan, seyrek raporlayan cihazlarBirkaç dakika veya bağlan–publish et–bağlantıyı kesDaha az radyo uyanması; kalıcı oturumlara güvenin

Keep alive kaynaklı bağlantı kopmalarını gidermek

Client’lar her 1,5× keep alive’da bir bağlantıyı kaybediyorsa olağan neden çalışmayan bir client döngüsüdür — örneğin Paho’nun ağ döngüsünün bir callback içindeki uzun süren bir iş yüzünden bloklanması ve bu yüzden hiç PINGREQ gönderilmemesi. Birkaç dakikalık sabit aralıklarla sık sık yeniden bağlanma ise bir proxy veya NAT üzerindeki boşta kalma zaman aşımına işaret eder. Diğer nedenler için MQTT bağlantı hataları rehberine bakın.

Sıkça sorulan sorular

İyi bir MQTT keep alive aralığı nedir?

Kararlı ağlardaki çoğu cihaz için 30–60 saniye mantıklı bir varsayılandır. Ölü client’ları hızla tespit etmeniz veya agresif bir NAT zaman aşımının altında kalmanız gerekiyorsa daha kısa değerler (15–30 saniye), her radyo uyanmasının enerjiye mal olduğu pilli cihazlarda ise daha uzun değerler kullanın.

MQTT keep alive zaman aşımına uğradığında ne olur?

Broker, keep alive aralığının bir buçuk katı içinde client’tan hiçbir kontrol paketi almazsa ağ bağlantısını kapatır ve bunu anormal bir bağlantı kesilmesi olarak değerlendirir. Bu, varsa Last Will mesajının publish edilmesi demektir. MQTT 5’te broker önce 0x8D (Keep Alive timeout) reason code’lu bir DISCONNECT gönderebilir.

Keep alive’ı 0 yapmak onu devre dışı bırakır mı?

Evet. 0 değerindeki keep alive mekanizmayı kapatır, böylece broker client’ı boşta kaldığı için asla düşürmez. Bu nadiren iyi bir fikirdir; çünkü yarı açık TCP bağlantıları kimse fark etmeden çok uzun süre kalabilir.