MQTT receive maximum, karşı tarafa aynı anda kaç QoS 1 ve QoS 2 mesajının onaylanmamış şekilde "uçuşta" (in flight) olmasına razı olduğunuzu bildiren MQTT 5 ayarıdır. Bu rehberde bu akış kontrolü penceresinin her iki yönde nasıl çalıştığını, mikrodenetleyiciler ve yeniden bağlanma sonrası ani yükler için neden önemli olduğunu ve mosquitto, Python ve Node.js'te nasıl ayarlanacağını öğreneceksiniz.
Receive Maximum Hangi Sorunu Çözer?
MQTT 3.1.1'de standart bir akış kontrolü yoktu. Bir broker, QoS 1 mesajlarını TCP bağlantısının izin verdiği hızda bir istemciye gönderebiliyordu ve istemci, PUBACK gönderene kadar bunların her birini tamponlamak zorundaydı. Bu bir sunucuda işe yarar, ancak yalnızca birkaç kilobayt boş RAM'i olan bir mikrodenetleyicinin belleği tükenebilir, mesajlar düşebilir veya cihaz çökebilir. Sorun en çok, kalıcı bir oturumun kuyruktaki mesaj birikimini bir anda serbest bıraktığı yeniden bağlanmanın hemen ardından kendini gösterir.
Broker'lar ve kütüphaneler bununla başa çıkmak için kendi "max in-flight" ayarlarını icat etti, ancak bunlar müzakere edilmiyordu; dolayısıyla iki taraf da diğerinin sınırını bilmiyordu. MQTT 5 bu fikri Receive Maximum özelliği olarak standartlaştırdı.
MQTT Receive Maximum Penceresi Nasıl Çalışır?
Receive Maximum, her iki tarafın da bildirebileceği, 1 ile 65.535 arasında iki baytlık bir tam sayıdır:
- İstemci bunu CONNECT içinde gönderir: "Broker, bana N'den fazla onaylanmamış QoS 1/2 PUBLISH paketi gönderme."
- Broker bunu CONNACK içinde gönderir: "İstemci, bana N'den fazla onaylanmamış QoS 1/2 PUBLISH paketi gönderme."
Özellik yoksa değer varsayılan olarak 65.535'tir; bu da fiilen "sınır yok" anlamına gelir. 0 değerine izin verilmez.
Uçuşta Sayılanlar
| Paket türü | Pencereden düşer mi? | Ne zaman serbest kalır |
|---|---|---|
| QoS 0 PUBLISH | Hayır | Uygulanamaz |
| QoS 1 PUBLISH | Evet | PUBACK alındığında |
| QoS 2 PUBLISH | Evet | PUBCOMP alındığında (veya hata reason code'lu PUBREC) |
| Abonelikte gönderilen retained mesaj | QoS 1 veya 2 ile teslim edilirse evet | Normal onay |
| Kuyruktaki çevrimdışı mesajlar | QoS 1 veya 2'de evet | Normal onay |
Gönderen taraf bir sayaç tutar (spesifikasyon buna send quota der). Her QoS 1 veya 2 PUBLISH sayacı bir azaltır; tamamlanan her onay bir artırır. Sayaç sıfıra ulaştığında gönderen QoS 1 ve 2 mesajlarını göndermeyi durdurup beklemek zorundadır. QoS 0 mesajlarını göndermeye yine devam edebilir ve spesifikasyon PINGREQ göndermeyi sürdürmesine de izin verir; dolayısıyla keep alive etkilenmez.
Sınır Aşılırsa Ne Olur?
Bir gönderen pencereyi yok sayarsa ve alıcı, bildirdiğinden daha fazla onaylanmamış QoS 1/2 mesajı alırsa, alıcı 0x93 (Receive Maximum exceeded) reason code'uyla bağlantıyı kesmelidir. Pratikte bunu nadiren görürsünüz, çünkü yaygın kütüphaneler pencereyi otomatik olarak uygular. Gördüğünüzde ise neredeyse her zaman özel yazılmış veya çok eski bir istemci uygulamasına işaret eder.
Yavaş Cihazlar için Neden Önemlidir?
10 dakikalık bir Wi-Fi kesintisinden sonra yeniden bağlanan bir ESP32 düşünün. Oturumunda kuyruğa alınmış 200 QoS 1 yapılandırma güncellemesi bulunuyor. Akış kontrolü olmadan broker 200 mesajın hepsini bir anda gönderebilir. Receive maximum değeri 5 olduğunda broker beş mesaj gönderir, PUBACK'leri bekler, ardından her onay geldikçe yenilerini gönderir. Bellek kullanımı sınırlı kalır, işleme hızı yetişir ve cihaz yanıt vermeye devam eder.
Pencere, backend tüketicileri için de doğal bir geri basınç (back-pressure) sağlar: bir worker PUBACK'i yalnızca mesajı veritabanına yazdıktan sonra gönderiyorsa, küçük bir receive maximum, broker'ın worker'ın kaldırabileceğinden fazla iş yığmasını engeller. Bu, birkaç worker'ın tek bir akışı paylaştığı ve her worker'ın penceresinin uçuştaki işlerden aldığı payı sınırladığı MQTT paylaşımlı abonelikleri için faydalı bir tamamlayıcıdır.
İstemcilerde Receive Maximum Ayarlamak
broker.connectmq.com adresindeki herkese açık MQTT test broker'ında connectmq/demo/r2m6/... gibi benzersiz bir önekle test edin. Herkese açık alan herkese açıktır; bu yüzden sahte payload'lar kullanın.
mosquitto_sub
mosquitto_sub -h broker.connectmq.com -p 1883 -V mqttv5 \
-i recvmax-demo-r2m6 -q 1 -v -d \
-D connect receive-maximum 5 \
-t 'connectmq/demo/r2m6/#'
-d çıktısı, gönderdiğiniz CONNECT özelliklerini ve broker'ın döndürdüğü CONNACK özelliklerini (broker bir değer ayarladıysa kendi receive maximum değeri dahil) gösterir.
Python (paho-mqtt 2.x)
import time
import paho.mqtt.client as mqtt
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes
def on_connect(client, userdata, flags, reason_code, properties):
server_rm = getattr(properties, "ReceiveMaximum", 65535)
print("Connected:", reason_code, "| broker receive maximum:", server_rm)
client.subscribe("connectmq/demo/r2m6/#", qos=1)
def on_message(client, userdata, msg):
# Yavaş bir cihazı simüle et; paho PUBACK'i bu callback döndükten sonra gönderir
time.sleep(0.5)
print("Handled", msg.topic, msg.payload.decode())
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id="recvmax-py-r2m6",
protocol=mqtt.MQTTv5)
client.on_connect = on_connect
client.on_message = on_message
# *Bizim* eş zamanlı olarak gönderdiklerimizi sınırla (giden pencere)
client.max_inflight_messages_set(10)
# Broker'dan *onun* bize gönderdiklerini sınırlamasını iste (gelen pencere)
props = Properties(PacketTypes.CONNECT)
props.ReceiveMaximum = 5
client.connect("broker.connectmq.com", 1883, keepalive=60, properties=props)
client.loop_forever()
Başka bir terminalden ani bir mesaj yükü publish edin ve mesajların sabit bir hızla gelişini izleyin:
for i in $(seq 1 30); do
mosquitto_pub -h broker.connectmq.com -p 1883 -i burst-r2m6 \
-q 1 -t 'connectmq/demo/r2m6/burst' -m "msg $i"
done
Callback içindeki time.sleep çağrısının paho'nun ağ döngüsünü de bloke ettiğini unutmayın. Bu gösterim için sorun değildir, ancak üretimde yavaş işleri ayrı bir thread'e taşıyıp döngüyü serbest tutun; aksi halde keep alive ping'leri gecikir.
Node.js (MQTT.js v5)
const mqtt = require("mqtt");
const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
clientId: "recvmax-node-r2m6",
protocolVersion: 5,
properties: { receiveMaximum: 5 },
});
client.on("connect", (connack) => {
console.log("broker properties:", connack.properties);
client.subscribe("connectmq/demo/r2m6/#", { qos: 1 });
});
client.on("message", (topic, payload) => {
console.log(topic, payload.toString());
});
Receive Maximum Değerini Seçmek
| İstemci | Önerilen değer | Neden |
|---|---|---|
| Mikrodenetleyici (ESP32, ESP8266) | 1 ila 10 | Sınırlı RAM, sıralı işleme |
| Raspberry Pi gateway | 10 ila 50 | Daha fazla bellek, ama hâlâ mütevazı CPU |
| Veritabanına yazan backend worker'ı | Kabaca sürdürebildiği paralel yazma sayısı | Geri basınç gerçek aktarım hızıyla eşleşir |
| Canlı değerleri gösteren dashboard | Varsayılan | Çoğunlukla sınırlanmayan QoS 0 trafiği |
1 değeri katı biçimde tek tek işleme sağlar; bu da sıralama mantığını basitleştirebilir, ancak yüksek gecikmeli bağlantılarda aktarım hızından ödün verir. Uçuştaki her yuva bir gidiş dönüş gerektirir; bu nedenle yüksek gecikmeli bir hücresel bağlantıda çok küçük bir pencere aktarım hızını belirgin şekilde sınırlayabilir. Gerçek trafiğinizle ölçün.
Receive Maximum ve Mesaj Sıralaması
1'den büyük bir pencere MQTT sıralama garantilerini bozmaz: broker bir topic'teki mesajları hâlâ aldığı sırayla gönderir ve istemci de onları o sırayla alır. Değişen şey, aynı anda kaç mesajın onay bekleyebileceğidir. Uygulamanız mesajları sırasız onaylıyorsa, örneğin bir thread havuzuna devrederek, işleme sırası protokolün değil sizin sorumluluğunuzdadır. Pencere tek bir tarafta yapılandırılmak yerine protokolün kendisi tarafından müzakere edildiği için davranış; ConnectMQ broker'ına, yerel bir Mosquitto'ya veya başka herhangi bir MQTT 5 broker'ına bağlansanız da aynıdır.
Sorun Giderme Kontrol Listesi
- Yeniden bağlandıktan sonra mesajlar yavaş geliyor. Bu, pencerenin çalıştığını gösterir. Cihaz kaldırabiliyorsa değeri artırın veya message expiry ile birikimi azaltın.
- Cihazın belleği hâlâ tükeniyor. Trafiğin çoğunun QoS 0 olup olmadığını kontrol edin; Receive Maximum onu sınırlamaz. Maksimum paket boyutunu da kontrol edin.
- Publisher takılıyor. Broker'ın receive maximum değeri küçük olduğu veya PUBACK'ler yavaş geldiği için istemcinizin send quota'sı sıfıra ulaştı. CONNACK özelliklerini loglayın.
- 0x93 ile bağlantı kesiliyor. Bir istemci izin verilenden fazla uçuşta mesaj gönderdi; istemci kütüphanesini güncelleyin veya düzeltin.
- Ayarın hiçbir etkisi yok. MQTT 3.1.1 ile bağlanıyorsunuz. Receive Maximum yalnızca MQTT 5'te vardır.
Kuyruktaki mesajların en başta nasıl biriktiğine dair daha geniş bir bakış için MQTT'nin çevrimdışı istemciler için mesajları nasıl kuyruğa aldığına göz atın. Protokolde yeni misiniz? MQTT eğitimi ile başlayın.
Akış Kontrolünü ConnectMQ'da Ayarlayın
ConnectMQ, MQTT 3.1.1 ve 5.0'ı TCP, TLS, WebSocket ve güvenli WebSocket üzerinde çalıştırır; böylece Receive Maximum gibi MQTT 5 özellikleri her istemciden çalışır. Plan bazlı kotalar ve taşma koruması paylaşılan bir buluttaki MQTT broker'ını kararlı tutarken Receive Maximum tek tek cihazlarınızı korur. Kredi kartı gerektirmeden ücretsiz bir Serverless broker oluşturun, YOUR_USERNAME, YOUR_PASSWORD ve YOUR_CLIENT_ID ile bağlanın ve cihazlarınıza test amaçlı ani yükler göndermek için portalın tarayıcı içi istemcisini kullanın. Üretim filoları için yönetilen bir MQTT broker broker operasyon işini tamamen ortadan kaldırır.
Sık Sorulan Sorular
Varsayılan MQTT receive maximum değeri nedir?
Özellik gönderilmezse receive maximum 65.535'tir; bu da fiilen pratik bir sınır olmadığı anlamına gelir. Akış kontrolü elde etmek için istemcilerin açıkça daha küçük bir değer ayarlaması gerekir.
Receive maximum QoS 0 mesajlarını sınırlar mı?
Hayır. Yalnızca henüz onaylanmamış QoS 1 ve QoS 2 PUBLISH paketlerini sayar. QoS 0 mesajları bu anlamda hiçbir zaman uçuşta değildir.
Receive maximum MQTT 3.1.1'de mevcut mu?
Hayır. Bu bir MQTT 5 özelliğidir. MQTT 3.1.1 istemcileri, broker'a iletilmeyen kütüphaneye özgü uçuş ayarlarına güvenir.
0x93 reason code'u ne anlama gelir?
Receive Maximum exceeded anlamına gelir: gönderenin uçuşta, alıcının izin verdiğinden fazla onaylanmamış QoS 1 veya 2 mesajı vardı; bu yüzden alıcı bağlantıyı kapattı.



