Bir MQTT oturumu (session), broker ile client’ın birbirleri hakkında tuttuğu durum bilgisidir: client’ın hangi topic’lere abone olduğu ve hangi mesajların hâlâ yolda olduğu. Kalıcı oturumda (persistent session) bu durum bağlantı kesildikten sonra da korunur; böylece birkaç dakikalığına ağdan düşen bir cihaz aynı aboneliklere geri döner ve kaçırdığı mesajları alır. Bu yazı oturumların MQTT 3.1.1’de (cleanSession) ve MQTT 5’te (Clean Start ve Session Expiry Interval) nasıl çalıştığını açıklıyor.
Bir oturum neleri içerir?
Spesifikasyon her iki taraftaki oturum durumunu tanımlar. Broker tarafında şunları içerir:
- Client ID ile tanımlanan oturumun kendisinin varlığı.
- Client’ın abonelikleri (topic filtreleri ve QoS’ları).
- Client’a gönderilmiş ancak henüz tamamen onaylanmamış QoS 1 ve QoS 2 mesajları.
- Client’a gönderilmeyi bekleyen QoS 1 ve QoS 2 mesajları — “çevrimdışı kuyruk”.
- Client’tan alınmış ancak henüz tamamen onaylanmamış QoS 2 mesajları.
- İsteğe bağlı olarak, gönderilmeyi bekleyen QoS 0 mesajları (broker’lar bunları kuyruğa almayı seçebilir, ancak genellikle almaz).
Client kendi yarısını tutar: gönderdiği ama tamamen onaylanmamış QoS 1 ve 2 mesajları ile aldığı ama tamamlamadığı QoS 2 mesajları. QoS seviyelerinin garantilerini yeniden bağlanmalar boyunca yalnızca kalıcı oturum kullanıldığında sağlamasının nedeni budur.
MQTT 3.1.1: cleanSession bayrağı
MQTT 3.1.1’de CONNECT paketindeki tek bir bit her şeye karar verir:
| cleanSession | Bağlanırken | Bağlantı kesilince |
|---|---|---|
1 (true) | Bu client ID’ye ait mevcut oturum silinir; yeni bir oturum başlar | Oturum silinir |
0 (false) | Mevcut oturum devam ettirilir; yoksa yeni bir oturum oluşturulur | Oturum korunur ve aboneliklerine ait QoS 1/2 mesajları kuyruğa alınır |
Protokole göre 3.1.1’deki kalıcı bir oturumun süresi kendiliğinden hiç dolmaz. Broker’lar, Mosquitto’nun persistent_client_expiration ve max_queued_messages ayarları gibi kendi sınırlarını ekler; aksi halde terk edilmiş client ID’ler sonsuza kadar birikirdi. Sıfır uzunlukta bir client ID’ye yalnızca cleanSession=1 ile izin verilir, çünkü tanımlanamayan bir oturum devam ettirilemez.
MQTT 5: Clean Start ve Session Expiry Interval
MQTT 5 eski bayrağı birbirinden bağımsız iki kontrole ayırır:
- Clean Start (bir bayrak) — bağlanırken mevcut oturumun silinip silinmeyeceği.
- Session Expiry Interval (saniye cinsinden bir
CONNECTözelliği) — ağ bağlantısı kapandıktan sonra broker’ın oturumu ne kadar süre tutacağı. Belirtilmemesi veya0olması oturumun bağlantıyla birlikte bittiği,0xFFFFFFFFise süresinin hiç dolmadığı anlamına gelir.
Bu, 3.1.1’in ifade edemediği kombinasyonlar sunar; örneğin “her zaman sıfırdan başla, ama bağlantım düşerse oturumumu bir saat tut” (Clean Start = 1, expiry = 3600). Client, 0 expiry ile bağlanmadığı sürece süreyi DISCONNECT paketinde de değiştirebilir.
| MQTT 3.1.1 | MQTT 5’teki karşılığı |
|---|---|
cleanSession = 1 | Clean Start = 1, Session Expiry Interval = 0 |
cleanSession = 0 | Clean Start = 0, Session Expiry Interval = 0xFFFFFFFF |
MQTT 5 broker’ları talep edilen süreyi kısaltabilir ve gerçek değeri CONNACK içindeki bir Session Expiry Interval özelliğiyle bildirebilir. Kuyruktaki komutların, geçerliliklerini yitirmelerinden saatler sonra teslim edilmemesi için bunu mesaj başına Message Expiry Interval ile birleştirin. Diğer farklar MQTT 5 ve 3.1.1 yazısında ele alınıyor.
Session Present bayrağı
Broker’ın CONNACK paketi, client’a gerçekte ne olduğunu söyleyen bir Session Present bayrağı taşır:
1— broker saklanmış bir oturum buldu ve devam ettirdi. Abonelikler hâlâ aktiftir; yeniden abone olmanız gerekmez.0— hiçbir oturum devam ettirilmedi (Clean Start set edilmişti, süresi doldu veya broker onu kaybetti). Client’ın yeniden abone olması gerekir.
Sağlam client’lar varsaymak yerine bu bayrağı kontrol eder. En güvenli basit kalıp, Session Present 0 olduğunda her seferinde yeniden abone olmaktır; 1 iken yeniden abone olmaya izin verilir, ancak bu mevcut aboneliklerin yerini alır ve retained mesajların yeniden gönderilmesine neden olabilir.
Örnekler
Mosquitto CLI’da -c clean session’ı devre dışı bırakır, -i ise sabit bir client ID belirler — kalıcı bir oturum için ikisi de gereklidir:
# 1. Create the session, then press Ctrl+C
mosquitto_sub -h broker.hivemq.com -i sensor-42-sub -c -q 1 -t 'testmqtt/sess-demo/#'
# 2. While it is offline, publish with QoS 1
mosquitto_pub -h broker.hivemq.com -q 1 -t 'testmqtt/sess-demo/cmd' -m 'reboot'
# 3. Reconnect with the same ID: the queued message is delivered
mosquitto_sub -h broker.hivemq.com -i sensor-42-sub -c -q 1 -t 'testmqtt/sess-demo/#'import mqtt from 'mqtt';
const client = mqtt.connect('wss://broker.hivemq.com:8884/mqtt', {
protocolVersion: 5,
clientId: 'sensor-42-sub',
clean: false, // Clean Start = 0
properties: { sessionExpiryInterval: 3600 },
});
client.on('connect', (connack) => {
if (!connack.sessionPresent) {
client.subscribe('testmqtt/sess-demo/#', { qos: 1 });
}
});import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, reason_code, properties):
if not flags.session_present:
client.subscribe("testmqtt/sess-demo/#", qos=1)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id="sensor-42-sub", clean_session=False)
client.on_connect = on_connect
client.connect("broker.hivemq.com", 1883)
client.loop_forever()Diğer diller için eşdeğer kodu MQTT kod oluşturucu ile üretebilir, sabit ve benzersiz ID’ler oluşturmak için client ID oluşturucuyu kullanabilirsiniz. Test mesajlarını tarayıcınızdan publish etmek için online client’ı kullanın:
Online MQTT istemcisinde deneyin
Bir oturum ne kadar yaşamalı?
MQTT 5’te bir Session Expiry Interval seçmeniz gerekir; doğru değer, client’ın gerçekçi olarak ne kadar süre uzakta kalıp yine de kaçırdıklarını önemseyeceğine bağlıdır:
- Mobil uygulamalar ve panolar — dakikalar. Bir tüneli veya ağ geçişini atlatacak kadar uzun, uygulamayı kapatmış kullanıcılar için broker’ın durum tutmayacağı kadar kısa.
- Güvenilmez bağlantılardaki saha cihazları — tipik kesinti sürelerine göre saatlerden bir güne kadar.
- Backend tüketicileri — yeni bir sürüm başlarken hiçbir mesaj kaybolmasın diye bir deployment veya yeniden başlatma süresini kapsayacak kadar uzun.
Oturumlar Last Will ile de etkileşir. MQTT 5’te will mesajı, Will Delay Interval dolduğunda veya oturum bittiğinde (hangisi önce gelirse) publish edilir. Kısa bir will gecikmesi ile daha uzun bir oturum, cihazın kısa bir aksaklıktan sonra bir “offline” alarmı tetiklemeden sessizce yeniden bağlanmasını sağlar.
Sık karşılaşılan tuzaklar
- Rastgele client ID’ler. Birçok kütüphane her başlatmada rastgele bir ID üretir; bu da her seferinde sessizce yeni bir oturum oluşturur. Kalıcı oturumlar sabit bir ID gerektirir.
- Zincirin bir yerinde QoS 0. Teslim QoS’u, publish ve abonelik QoS’undan düşük olanıdır. Bunlardan biri 0 ise mesajlar çevrimdışı client’lar için kuyruğa alınmaz.
- Aynı ID’ye sahip iki client. Yeni olan bağlandığında broker eskisinin bağlantısını keser ve ikisi oturum için kavga eder. Bkz. MQTT bağlantı hataları.
- Sınırsız kuyruklar. Günlerce çevrimdışı kalan bir cihaz büyük bir birikim oluşturabilir. Bunu kontrol altında tutmak için oturum ve mesaj expiry’sini ve broker kuyruk sınırlarını kullanın.
- Broker’ın yeniden başlaması. Oturumlar, broker’ın yeniden başlamasından yalnızca broker onları diske yazıyorsa sağ çıkar (Mosquitto için
persistence true).
Kalıcı oturumlar ne zaman kullanılmalı?
Komutları veya yapılandırma güncellemelerini kaçırmaması gereken cihazlar ve her QoS 1 mesajını işlemesi gereken backend tüketicileri için kullanın. Kısa ömürlü araçlar, yalnızca en son değerleri önemseyen panolar (bunu retained mesajlar karşılar) ve geçici client ID’lerle bağlanan her şey için clean session’ları tercih edin. Kararsız ağlarda, bağlantı kopmalarının hızla tespit edilip kuyruğun devreye girmesi için kalıcı bir oturumu makul bir keep alive aralığıyla birlikte kullanın.
Sıkça sorulan sorular
MQTT’de clean session false ne anlama gelir?
MQTT 3.1.1’de cleanSession false olduğunda broker, client bağlantıyı kestikten sonra oturumunu korur: aboneliklerini ve client çevrimdışıyken gelen tüm QoS 1 ve QoS 2 mesajlarını. Client aynı client ID ile yeniden bağlandığında bu oturumu devam ettirir ve kuyruktaki mesajları alır.
Kalıcı oturuma rağmen çevrimdışı mesajları neden alamıyorum?
Dört şeyi kontrol edin: client tam olarak aynı client ID ile yeniden bağlanıyor mu, clean session false mu (MQTT 5’te sıfırdan farklı bir Session Expiry Interval ile Clean Start false mu), hem abonelik hem de publish QoS 1 veya 2 kullanıyor mu ve broker kuyruk sınırına veya oturum süresinin sonuna ulaşmış mı.
Clean Session ile Clean Start arasındaki fark nedir?
MQTT 3.1.1’de cleanSession, hem bağlanırken eski oturumun silinip silinmeyeceğini hem de yeni oturumun bağlantı kesildikten sonra korunup korunmayacağını kontrol eder. MQTT 5 bunları ayırır: Clean Start yalnızca eski oturumun silinmesini, Session Expiry Interval ise oturumun bağlantı kesildikten sonra ne kadar yaşayacağını kontrol eder.