MQTT kalıcı oturumu (persistent session), istemcinin bağlantısı kesik olsa bile broker'ın istemcinin kim olduğunu, nelere abone olduğunu ve ona hâlâ hangi mesajları borçlu olduğunu hatırlamasını sağlar. Bu yazının sonunda broker'ın tam olarak neleri sakladığını, clean session bayrağının (ve MQTT 5'teki karşılığının) bunu nasıl kontrol ettiğini ve bu davranışı birkaç komutla kendiniz nasıl doğrulayacağınızı öğrenmiş olacaksınız.
MQTT Kalıcı Oturum Nedir?
Her MQTT bağlantısının bir oturumu vardır: istemci ile MQTT broker arasında paylaşılan bir durum paketi. Temiz (kalıcı olmayan) bir oturumda bu durum yalnızca ağ bağlantısı sürdüğü müddetçe yaşar. Bağlantı kesildiğinde broker her şeyi atar. Kalıcı bir oturumda ise broker, bağlantı kapandıktan sonra durumu saklar ve aynı istemci yeniden bağlandığında ona geri verir.
Eski oturumu yeni bağlantıya bağlayan kimlik client ID'dir. Kalıcı oturumların yalnızca istemci her seferinde tam olarak aynı kimlikle yeniden bağlandığında çalışmasının nedeni budur.
Broker'ın Sakladıkları
| Broker'daki oturum durumu | Kalıcı oturumla saklanır mı? |
|---|---|
| İstemcinin abonelikleri (topic filtreleri ve QoS) | Evet |
| İstemci çevrimdışıyken gelen QoS 1 ve QoS 2 mesajları | Evet |
| Gönderilmiş ama henüz onaylanmamış QoS 1 ve QoS 2 mesajları | Evet |
| İstemciden alınmış ama tamamlanmamış QoS 2 mesajları | Evet |
| İstemci çevrimdışıyken publish edilen QoS 0 mesajları | Hayır (broker'lar isteğe bağlı olarak kuyruğa alabilir, çoğu almaz) |
| Retained mesajlar | Oturum durumu değildir; herkes için topic bazında saklanır |
İstemci kendi yarısını tutar: gönderdiği ama henüz onaylanmamış QoS 1 ve 2 mesajları ile aldığı ama henüz tamamlamadığı QoS 2 mesajları. Bunu yalnızca bellekte tutan bir istemci kütüphanesi, yeniden başlatmada kendi yarısını kaybeder; bu da sık rastlanan bir kafa karışıklığı kaynağıdır.
Ne Yapmaz?
Kalıcı oturum bir veritabanı değildir. Geçmişi saklamaz, istemcinin zaten onayladığı mesajları yeniden oynatmaz ve QoS 0 trafiğini güvenilir şekilde teslim etmez. Ayrıca yalnızca istemcinin çevrimdışı olmadan önce zaten abone olduğu topic'lerin mesajlarını tutar. Oturumlardan bağımsız olarak bir topic'in "en son değerine" ihtiyacınız varsa bunun yerine retained mesajları kullanın.
MQTT 3.1.1'de Clean Session Bayrağı
MQTT 3.1.1'de CONNECT içindeki tek bir bit her şeyi kontrol eder:
- cleanSession = true: mevcut oturumu atar, sıfırdan başlar ve istemcinin bağlantısı kesildiğinde bu oturumu da atar.
- cleanSession = false: bu client ID için mevcut bir oturum varsa onu sürdürür, yoksa yeni bir oturum oluşturur ve bağlantı kesildikten sonra da saklar.
Broker, ne olduğunu istemciye CONNACK içindeki Session Present bayrağıyla bildirir. cleanSession = false ile bağlandıysanız ve Session Present 0 ise broker'da sizin için bir durum yoktur, dolayısıyla yeniden abone olmanız gerekir. 1 ise abonelikleriniz hâlâ yerindedir ve kuyruktaki mesajlar gelmek üzeredir.
3.1.1'in zayıf yanı, kalıcı oturumların yerleşik bir sona erme süresinin olmamasıdır. Hizmetten çıkarılan bir cihaz, broker'ın kendi sınırları devreye girene kadar mesaj toplamaya devam eden bir oturum bırakır.
MQTT 5'te Kalıcı Oturumlar
MQTT 5, bu bayrağı iki bağımsız kontrole ayırır:
- Clean Start, bağlantı anında mevcut bir oturumun atılıp atılmayacağına karar verir.
- Session Expiry Interval, oturumun bağlantı kesildikten sonra saniye cinsinden ne kadar süre yaşayacağına karar verir.
Dolayısıyla MQTT 5'te kalıcı oturum, Clean Start = false ile sıfırdan büyük bir Session Expiry Interval değerinin birleşimidir. Tam eşleştirme ve değerlerin nasıl seçileceği MQTT 5 clean start ve session expiry interval yazısında ele alınıyor. Broker'lar talep ettiğiniz süreyi sınırlayabilir; broker.connectmq.com adresindeki herkese açık test broker'ında maksimum değer 30 dakikadır.
MQTT Kalıcı Oturumu Adım Adım Deneyin
Bu deney herkese açık MQTT test broker'ını kullanır. Diğer okuyucularla çakışmamak için p9k2 yerine kendi rastgele sonekinizi seçin ve herkese açık alan herkes tarafından okunabildiği için hassas veri göndermeyin.
- Sabit bir kimlik, kalıcı oturum ve QoS 1 ile bir subscriber başlatın:
mosquitto_sub -h broker.connectmq.com -p 1883 -V mqttv5 \
-i persist-demo-p9k2 -c -x 1800 -q 1 -v \
-t 'connectmq/demo/p9k2/alerts'
-c clean start'ı devre dışı bırakır, -x 1800 ise 30 dakikalık bir session expiry ister.
Subscriber'ı Ctrl+C ile durdurun.
Subscriber çevrimdışıyken üç QoS 1 mesajı publish edin:
for i in 1 2 3; do
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-demo-p9k2 \
-q 1 -t 'connectmq/demo/p9k2/alerts' -m "alert $i"
done
Tam olarak aynı subscriber komutunu yeniden çalıştırın. Broker üç mesajı oturumunuzda kuyruğa aldığı için mesajlar hemen gelir.
Testi
-colmadan tekrarlayın. Bu sefer yeniden bağlandığınızda hiçbir şey gelmez: oturum temizlenmiştir.
Aynı Test Python ile
import paho.mqtt.client as mqtt
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes
TOPIC = "connectmq/demo/p9k2/alerts"
def on_connect(client, userdata, flags, reason_code, properties):
print("Connected:", reason_code, "session present:", flags.session_present)
if not flags.session_present:
# Broker'da bizim için oturum yok: yeniden abone ol
client.subscribe(TOPIC, qos=1)
def on_message(client, userdata, msg):
print(msg.topic, msg.payload.decode())
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id="persist-py-p9k2",
protocol=mqtt.MQTTv5,
)
client.on_connect = on_connect
client.on_message = on_message
props = Properties(PacketTypes.CONNECT)
props.SessionExpiryInterval = 1800 # saniye
client.connect("broker.connectmq.com", 1883, keepalive=60,
clean_start=False, properties=props)
client.loop_forever()
Abone olmadan önce session_present değerini kontrol etmek yerleşik bir kalıptır: gereksiz yeniden abonelikleri önler ve oturumun süresi dolduğunda doğru şekilde toparlanır.
Kalıcı Oturum Ne Zaman Kullanılmalı?
Bir mesajı kaçırmanın önemli olduğu ve istemcinin sabit bir kimlikle yeniden bağlandığı durumlarda kullanın:
- Komut alan (vanayı aç, yapılandırmayı güncelle) ve kısa süreliğine ağdan düşebilecek cihazlar.
- Alarm işleyicileri gibi her QoS 1 olayını işlemesi gereken backend tüketicileri.
- Uyanan, bağlanan, bekleyen komutları toplayan ve yeniden uykuya geçen pilli cihazlar.
Şu durumlarda temiz oturumu tercih edin:
- İstemci yalnızca canlı verilerle ilgileniyorsa, örneğin retained topic'lerden güncel değerleri gösteren bir dashboard.
- Client ID'ler rastgeleyse veya otomatik ölçeklenen web worker'ları gibi örnekler arasında yeniden kullanılıyorsa.
- Yalnızca publish ediyor, hiç abone olmuyorsanız; saklamaya değer pek bir oturum durumu yoktur.
Tuzaklar ve Sorun Giderme
- Rastgele client ID'ler. Birçok kütüphane, kimliği boş bırakırsanız rastgele bir kimlik üretir. Yeni bir kimlik her seferinde yeni bir oturum demektir, dolayısıyla hiçbir şey sürdürülmez. Sabit bir kimlik ayarlayın; bkz. MQTT client ID en iyi uygulamaları.
- QoS 0 ile abone olmak. Broker mesajları yalnızca abone olduğunuz QoS seviyesinde kuyruğa alır. Publisher QoS 1 kullanmış olsa bile QoS 0 aboneliği çevrimdışıyken hiçbir şey almaz.
- QoS 0 ile publish etmek. Teslimat, publish ve abonelik QoS değerlerinden düşük olanı kullanır. QoS 0 publish'ler kuyruğa alınmaz.
- İlk abonelikten önceki mesajları beklemek. Bir oturum yalnızca zaten sahip olduğu aboneliklerin mesajlarını kuyruğa alır.
- Yeniden bağlanmada oturum seli. Saatlerce çevrimdışı kalan bir cihaz, kuyruktaki mesajlardan oluşan ani bir yük alabilir. Tamponlarınızı buna göre boyutlandırın veya eski komutların kuyrukta ölmesi için MQTT 5 message expiry kullanın.
- Broker yeniden başlatmaları. Oturum depolama her broker'ın kendi uygulama ayrıntısıdır. ConnectMQ'da oturumlar bellekte tutulur; bu yüzden istemci bağlantı kesilmelerinden sağ çıkarlar ama broker yeniden başlatmasından sağ çıkmazlar. Tasarımınızı buna göre yapın: Session Present değerini kontrol edin, 0 ise yeniden abone olun ve her zaman erişilebilir olması gereken durumlar için retained mesajlar kullanın.
- Plan sınırları. ConnectMQ Serverless (Free) planı, kuyruklu teslimat için ihtiyacınız olan QoS 1'e kadar destek verir. QoS 2 ücretli planlarda mevcuttur.
Neyin ve ne kadarının kuyruğa alındığına daha yakından bakmak için MQTT'nin çevrimdışı istemciler için mesajları nasıl kuyruğa aldığını okuyun. Protokolde genel olarak yeni misiniz? MQTT eğitimi temellerden başlıyor.
Kalıcı Oturumları ConnectMQ'da Çalıştırın
ConnectMQ, MQTT 3.1.1 ve 5.0 desteğine sahip barındırılan bir MQTT broker'dır; böylece hem clean session bayrağı hem de MQTT 5 session expiry kutudan çıktığı gibi çalışır. Her broker oluşturulmuş kimlik bilgileriyle gelir ve client ID'ler bu kimlik bilgilerine bağlıdır; bu da bir yabancının cihazınızın oturumunu ele geçirmesini önler. Kredi kartı gerektirmeden ücretsiz Serverless planına kaydolun, YOUR_USERNAME, YOUR_PASSWORD ve YOUR_CLIENT_ID ile bağlanın ve yukarıdaki testi kendi özel broker'ınızda tekrarlayın.
Sık Sorulan Sorular
MQTT kalıcı oturumu QoS 0 mesajlarını saklar mı?
Genellikle hayır. Spesifikasyon yalnızca QoS 1 ve QoS 2 mesajlarının kuyruğa alınmasını zorunlu kılar; QoS 0 mesajlarını saklamak isteğe bağlıdır ve çoğu broker bunu yapmaz. Kaybetmeyi göze alamayacağınız her şey için QoS 1 kullanın.
Yeniden bağlandıktan sonra kuyruktaki mesajları neden alamıyorum?
En yaygın nedenler değişmiş bir client ID, clean session veya clean start true olarak ayarlanmış şekilde bağlanmak, QoS 0 aboneliği ya da süresi zaten dolmuş bir oturumdur. Oturumun sürdürülüp sürdürülmediğini görmek için CONNACK içindeki Session Present bayrağını kontrol edin.
Kalıcı oturumla yeniden abone olmam gerekir mi?
Yalnızca Session Present 0 ise. Broker oturumunuzu sürdürdüğünde abonelikleriniz zaten mevcuttur ve abone olma adımını atlayabilirsiniz.
Kalıcı oturumlar broker yeniden başlatmasından sağ çıkar mı?
Bu broker'a bağlıdır. ConnectMQ oturumları bellekte tutar; bu yüzden istemci bağlantı kesilmelerinden sağ çıkarlar ancak broker yeniden başlarsa temizlenirler. İstemciler Session Present = 0 durumunu sorunsuz şekilde ele almalıdır.



