Protokole göre maksimum MQTT mesaj boyutu 268.435.455 bayt, yani yaklaşık 256 MB'tır. Pratikte oraya asla ulaşmazsınız: broker'lar, bulut servisleri ve istemci kütüphaneleri daha düşük sınırlar koyar, bazıları da çok büyük mesajları size haber vermeden atar. Bu rehber her sınırın nerede tanımlandığını, MQTT 5'in bunu nasıl görünür kıldığını ve bir firmware imajı ya da kamera görüntüsü sizden önce bulmadan broker'ınızın gerçek tavanını nasıl test edeceğinizi anlatıyor.
256 MB sınırı nereden geliyor?
Her MQTT kontrol paketi, Remaining Length değerini içeren sabit bir başlıkla (fixed header) başlar: ardından gelen bayt sayısı. Bu değer, her biri yedi faydalı bit taşıyan en fazla dört baytlık değişken uzunluklu bir tamsayı olarak kodlanır; dolayısıyla en büyük değer 2^28 − 1 = 268.435.455'tir.
Bu sayı sadece verinizi değil, paketin geri kalanının tamamını kapsar. Bir PUBLISH ayrıca şunları içerir:
- topic adı (2 baytlık uzunluk + UTF-8 baytları),
- QoS 1 ve 2 için 2 baytlık packet identifier,
- MQTT 5'te bir özellikler (properties) bloğu (content type, user properties, message expiry…).
Yani mümkün olan en büyük payload 256 MB'ın biraz altındadır ve uzun topic'ler ile çok sayıda user property kullandıkça küçülür. MQTT paket boyutu hesaplayıcısı, belirli bir topic, QoS ve payload için kesin ek yükü gösterir.
Gerçekte karşılaştığınız sınırlar
| Katman | Sınırın tanımlandığı yer | Aşıldığında tipik davranış |
|---|---|---|
| Protokol | Remaining Length (4 bayt) | Paket hiç kodlanamaz |
| Mosquitto | max_packet_size, eskiden message_size_limit | MQTT 5: 0x95 ile bağlantı kesilir; 3.1.1: mesaj atılır veya bağlantı kapatılır |
| EMQX | mqtt.max_packet_size (varsayılan 1 MB) | Bağlantı kapatılır, broker log'unda hata görünür |
| HiveMQ | MQTT yapılandırmasındaki max-packet-size | MQTT 5 istemcileri 0x95 alır; 3.1.1 istemcilerinin bağlantısı kesilir |
| Bulut IoT servisleri | Servis kotaları | AWS IoT Core payload'ları 128 KB, Azure IoT Hub device-to-cloud mesajları 256 KB ile sınırlar; güncel kota sayfalarını kontrol edin |
| İstemci kütüphanesi | Dahili buffer'lar, MQTT 5 Maximum Packet Size | Publish hatası veya alırken sessizce atma |
| Ağ yolu | Proxy'ler, load balancer'lar, WebSocket gateway'leri | Yavaş hatlarda timeout veya reset |
Varsayılan değerler sürümden sürüme değişir; bu tabloyu garanti edilmiş sayıların listesi olarak değil, nereye bakacağınızı gösteren bir harita olarak kullanın. Çalıştırdığınız sürümün yapılandırma referansını okuyun.
Mosquitto yapılandırması
Mosquitto 2.x'te birbiriyle ilişkili iki seçenek vardır:
# Maximum size of any MQTT packet the broker accepts, in bytes.
# MQTT 5 clients are told this value in CONNACK.
max_packet_size 1048576
# Older option: maximum PUBLISH payload size. Deprecated in favour of
# max_packet_size, but still found in many existing configs.
# message_size_limit 1048576İkisi de ayarlanmamışsa Mosquitto protokol sınırından daha düşük bir sınır uygulamaz; yani tek bir istemci broker'ın yüzlerce megabayt bellek ayırmasına neden olabilir. Açık bir sınır koymak makul bir production yapılandırmasının parçasıdır; mosquitto.conf oluşturucu bunu da içerir.
MQTT 5 Maximum Packet Size
MQTT 3.1.1'de boyut pazarlığı yoktur. MQTT 5, her iki yönde de Maximum Packet Size özelliğini ekler:
- CONNECT → broker: İstemci almaya hazır olduğu en büyük paketi bildirir. Broker bundan büyük bir şey gönderemez; eşleşen bir mesaj bu subscriber için çok büyükse broker onu yalnızca bu istemci için atar.
- CONNACK → istemci: Broker kabul ettiği en büyük paketi bildirir. İyi yazılmış bir istemci kütüphanesi daha büyük paket göndermeyi reddeder. Yine de gönderilirse broker 0x95 Packet too large reason code'u ile bağlantıyı keser.
İnsanların aradığı hata bu ikinci durumdur. Anlamı ve ilgili kodlar MQTT reason code referansında yer alır, ayrıntılı açıklaması da MQTT packet too large makalesindedir.
mosquitto_pub ile hızlı test
Boyutu bilinen dosyalar üretin ve broker üzerinden gönderin. -f bir dosyayı payload olarak gönderir; -N ise mosquitto_sub'ın satır sonu eklemesini engeller, böylece bayt sayısı tam olarak doğru kalır.
HOST=broker.connectmq.com
TOPIC="testmqtt/payload-$RANDOM/blob"
for size in 64K 512K 1M 4M; do
head -c "$size" /dev/urandom > "/tmp/blob-$size"
done
# Terminal 1: bir mesaj al ve baytlarını say
mosquitto_sub -h "$HOST" -t "$TOPIC" -V mqttv5 -C 1 -W 30 -N | wc -c
# Terminal 2: her seferinde bir boyut gönder
mosquitto_pub -h "$HOST" -t "$TOPIC" -V mqttv5 -q 1 -f /tmp/blob-1M -d-d gönderilen ve alınan her paketi yazdırır; böylece PUBLISH'in istemciden çıkıp çıkmadığını ve bağlantının hemen ardından kapanıp kapanmadığını görürsünüz. wc -c dosya boyutunu yazdırıyorsa mesaj ulaşmıştır; mosquitto_sub 30 saniye sonra zaman aşımına uğruyorsa ulaşmamıştır. Kısıtlı bir subscriber'ı simüle etmek için mosquitto_sub komutuna -D connect maximum-packet-size 65536 ekleyin; büyük mesajların yalnızca o istemci için kaybolduğunu göreceksiniz.
Python ile otomatik boyut taraması
Tekrarlanabilir bir sonuç için bu paho-mqtt 2.x betiği, giderek büyüyen payload'ları QoS 1 ile yayınlar, her birini SHA-256 hash'i ile doğrular ve ilk hatada durur. Broker'ın bildirdiği sınırı da yazdırır.
import hashlib, os, threading, time, uuid
import paho.mqtt.client as mqtt
HOST, PORT = "broker.connectmq.com", 1883
TOPIC = f"testmqtt/payload-{uuid.uuid4().hex[:8]}/blob"
SIZES = [1_024, 65_536, 262_144, 1_048_576, 4_194_304, 16_777_216]
TIMEOUT = 30
result, got = {}, threading.Event()
def on_connect(client, userdata, flags, reason_code, properties):
limit = getattr(properties, "MaximumPacketSize", None)
print(f"connected: {reason_code}, broker max packet = {limit or 'not advertised'}")
def on_disconnect(client, userdata, flags, reason_code, properties):
print(f"disconnected: {reason_code}")
def on_message(client, userdata, msg):
result["digest"] = hashlib.sha256(msg.payload).hexdigest()
got.set()
def make_client(name):
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"{name}-{uuid.uuid4().hex[:6]}", protocol=mqtt.MQTTv5)
# c.username_pw_set(os.environ["MQTT_USER"], os.environ["MQTT_PASS"])
c.on_connect, c.on_disconnect, c.on_message = on_connect, on_disconnect, on_message
c.connect(HOST, PORT)
c.loop_start()
return c
sub = make_client("sweep-sub")
sub.subscribe(TOPIC, qos=1)
pub = make_client("sweep-pub")
time.sleep(2)
for size in SIZES:
payload = os.urandom(size)
got.clear()
start = time.perf_counter()
info = pub.publish(TOPIC, payload, qos=1)
if info.rc != mqtt.MQTT_ERR_SUCCESS:
print(f"{size:>10} B FAIL publish rc={info.rc}")
break
if not got.wait(TIMEOUT):
print(f"{size:>10} B FAIL not delivered within {TIMEOUT}s")
break
ok = result["digest"] == hashlib.sha256(payload).hexdigest()
print(f"{size:>10} B {'OK ' if ok else 'BAD '} {(time.perf_counter() - start) * 1000:.0f} ms")
pub.loop_stop(); sub.loop_stop()Tipik çıktılar ve anlamları:
- Tüm boyutlar OK: Broker en az 16 MB kabul ediyor. Gerçekten bunu isteyip istemediğinize karar verin.
- N boyutuna kadar teslim, sonra "not delivered", bağlantı kesilmesi yok: Broker çok büyük mesajları sessizce atıyor ya da subscriber'ın kendi sınırı devreye girdi.
- "disconnected: Packet too large":
max_packet_sizeuygulayan bir MQTT 5 broker'ı. Başarılı olan son boyut pratik tavanınızdır. - Gecikme boyutla birlikte sert biçimde artıyor: Broker'ı değil bant genişliğini ölçüyorsunuz. Değerleri upload hızınızla karşılaştırın.
Taramayı bir kez TCP üzerinden, bir kez de WebSockets üzerinden (/mqtt path'i ile 8083 veya 8084 portu) çalıştırın: WebSocket listener'larının önündeki proxy'lerin bazen kendi frame veya buffer sınırları olur. Tek tek payload'ları online MQTT istemcisinde etkileşimli olarak da deneyebilirsiniz.
Büyük payload'ların yan etkileri vardır
Broker 10 MB'lık bir mesajı kabul etse bile bunun bir bedeli vardır:
- Head-of-line blocking. MQTT tek bir TCP bağlantısı üzerinde çalışır. Büyük bir PUBLISH iletilirken bu bağlantıda başka hiçbir şey ilerlemez; küçük ve acil komutlar da PINGREQ paketleri de bekler. Yavaş bir hücresel bağlantıda bu, keep-alive zaman aşımlarına yol açabilir.
- Bellek. Broker genellikle mesajın tamamını bellekte tutar; çevrimdışı kalıcı oturumu olan her kuyruktaki subscriber için bir kez. Büyük retained mesajlar orada süresiz kalır.
- Yeniden gönderimler. QoS 1 veya 2'de kopan bir bağlantı, paketin tamamının yeniden gönderilmesi demektir; kaldığı yerden devam etme yoktur.
- Fan-out. 200 subscriber'a giden 5 MB'lık tek bir mesaj, 1 GB çıkış trafiği demektir. Hesabın detayı için MQTT bant genişliği ek yükü makalesine bakın.
Büyük veriler için tasarım kalıpları
- Mesajları varsayılan olarak küçük tutun. Telemetri, olaylar ve komutlar bayt ya da kilobayt düzeyinde olmalıdır. CBOR veya Protobuf gibi ikili kodlamalar JSON payload'larını belirgin şekilde küçültür.
- Büyük dosyaları parçalara bölün. Dosyayı
…/file/<id>/<n>üzerinde numaralı parçalara (örneğin 64 KB'lık) ayırın, toplam boyutu ve hash'i içeren bir manifest gönderin ve alıcı tarafta yeniden birleştirin. MQTT ile dosya transferi eksiksiz bir uygulamayı adım adım anlatır. - Dosyayı değil, işaretçiyi gönderin. Dosyayı HTTP ile bir nesne depolama alanına yükleyin, URL'yi ve metadata'yı MQTT ile yayınlayın. Kamera görüntüleri ve firmware için olağan tercih budur.
- Broker'da açık bir sınır belirleyin; en büyük meşru mesajınızın biraz üzerinde olsun ki hatalı davranan bir istemci belleği tüketemesin.
Tarayıcınızda test payload'ı yayınlayın
Protokolün 256 MB tavanı teorik bir sayıdır; önemli olan, istemci buffer'ından broker yapılandırmasına ve bulut kotasına kadar yolunuzdaki en küçük sınırdır. Bunu bir boyut taramasıyla ölçün, broker yapılandırmanızda açıkça tanımlayın ve daha büyük her şeyi tek bir mesaj yerine parçalar ya da işaretçiler olarak tasarlayın.
Sıkça sorulan sorular
Bir MQTT mesajının maksimum boyutu nedir?
Protokol, Remaining Length alanı en fazla dört bayt olduğu için 268.435.455 bayta (yaklaşık 256 MB) kadar kontrol paketlerine izin verir. Kullanılabilir payload biraz daha küçüktür ve neredeyse her broker ya da bulut servisi çok daha düşük bir sınır uygular.
Büyük MQTT mesajım neden hiçbir hata vermeden kayboluyor?
MQTT 3.1.1'de broker tek bir PUBLISH'i gerekçe belirterek reddedemez; bu yüzden pek çok broker çok büyük mesajları sessizce atar ya da bağlantıyı kapatır. MQTT 5 kullanın, CONNACK içindeki Maximum Packet Size değerini okuyun ve 0x95 Packet too large reason code'unu takip edin.
MQTT üzerinden dosya veya görsel göndermeli miyim?
Birkaç yüz kilobaytlık küçük dosyalar çoğu broker'da sorunsuz çalışır. Daha büyük dosyaları numaralı parçalara bölün ya da bir nesne depolama alanına giden URL'yi yayınlayın; böylece tek bir dev mesaj bağlantıyı tıkamaz ve broker belleğini tüketmez.

