Bir MQTT bağlantı stres testi basit bir soruyu yanıtlar: bu broker aynı anda kaç istemciyi tutabilir ve onları ne hızla kabul edebilir? Yöntem, broker'ın belleğini, CPU'sunu ve bağlantı gecikmesini izlerken boştaki bağlantıları kontrollü bir hızla artırmaktır — ve ulaştığınız limitin yükü üreten makineye değil, broker'a ait olduğundan emin olmaktır.
İlk denemelerin çoğu şüphe uyandıracak kadar yuvarlak bir sayıda takılır. Bu rehber istemci tarafındaki bu limitleri nasıl kaldıracağınızı, testi emqtt-bench veya bir Node.js betiğiyle nasıl çalıştıracağınızı ve her broker yeniden başlatmasının ardından gelen yeniden bağlanma fırtınasını nasıl simüle edeceğinizi gösterir.
Aslında neyi ölçüyorsunuz
| Metrik | Neden önemli |
|---|---|
| Maksimum eşzamanlı bağlantı | Broker'ın boşta tutabileceği filo büyüklüğü |
| Bağlantı hızı (CONNECT/sn) | Bir kesintiden sonra filonun ne kadar hızlı geri döndüğü |
| Bağlantı gecikmesi (p50/p99) | Yük altında TCP SYN'den CONNACK'e kadar geçen süre |
| Bağlantı başına broker belleği | Kapasite planlaması; tahmin etmeyin, ölçün |
| Hata türleri | Reddedilme, timeout, CONNACK reason code'ları |
Bağlantılar broker'a soket tamponları, oturum durumu ve abonelikler için bellek, TLS handshake'leri ve keep-alive işleme için de CPU maliyeti getirir. Bunların hepsi broker'a, sürüme ve yapılandırmaya bağlıdır; bu yüzden tek anlamlı sayı sizin ayarlarınızla ölçtüğünüz sayıdır: aynı TLS, aynı keep-alive, aynı kimlik doğrulama ve istemci başına yaklaşık aynı abonelik sayısı.
Önce yük üretecini düzeltin
Tek bir Linux makinesinde, düzgün bir broker pes etmeden çok önce giden bağlantıları sınırlayan üç limit vardır.
Dosya tanımlayıcıları
Her TCP soketi bir dosya tanımlayıcısıdır (file descriptor). Varsayılan soft limit çoğu zaman 1.024'tür:
ulimit -n # mevcut soft limit
ulimit -n 200000 # bu shell için yükselt (hard limite kadar)
cat /proc/sys/fs/file-max # sistem geneli tavanKalıcı bir değişiklik için /etc/security/limits.conf içinde nofile ayarlayın veya Docker'da --ulimit nofile=200000:200000 verin.
Geçici portlar
Tek bir kaynak IP'den aynı broker IP'si ve portuna yapılan her bağlantı benzersiz bir yerel port gerektirir. Linux'un varsayılan aralığı 32768–60999'dur, yani yaklaşık 28.000 port — testlerin klasik olarak takıldığı yer.
sysctl net.ipv4.ip_local_port_range
sudo sysctl -w net.ipv4.ip_local_port_range="1024 65000"Bu, kaynak IP başına yaklaşık 64.000 bağlantı sağlar. Bunun ötesinde daha fazla kaynak IP'ye (veya daha fazla broker portu/IP'si ya da daha fazla yük makinesine) ihtiyacınız vardır.
Bağlantı izleme
Yük üreteci bağlantı izlemeli bir güvenlik duvarı çalıştırıyorsa (Docker ve iptables ile yaygındır) conntrack tablosu dolabilir. Bu durumda kernel log'unda nf_conntrack: table full, dropping packet görünür.
sudo sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
sudo sysctl -w net.netfilter.nf_conntrack_max=262144Testi emqtt-bench ile çalıştırmak
emqtt-bench tam olarak bunun için yapılmıştır. conn komutu sabit bir hızla bağlantı açar ve onları canlı tutar:
docker run --rm -it --ulimit nofile=200000:200000 emqx/emqtt-bench conn \
-h "$MQTT_HOST" -p 1883 \
-c 10000 -R 500 -k 60 \
-u "$MQTT_USER" -P "$MQTT_PASS"MQTT_HOST değişkenini kendi broker'ınıza ayarlayın; paylaşılan broker.connectmq.com uç noktası yalnızca küçük smoke testler içindir. -c istemci sayısı, -R saniyedeki bağlantı hızı, -k ise saniye cinsinden keep-alive'dır. Cihazlarınızın kullandığı keep-alive değerini kullanın: daha kısa keep-alive, boştaki istemci başına daha fazla PINGREQ trafiği demektir.
Tek bir kaynak IP'nin ötesine geçmek için yük makinesine ikincil adresler ekleyin ve emqtt-bench'in istemcileri --ifaddr ile bu adreslere dağıtmasını sağlayın. Container'ın bu adresleri görmesi için host ağını kullanın:
docker run --rm -it --network host --ulimit nofile=200000:200000 \
emqx/emqtt-bench conn \
-h "$MQTT_HOST" -p 1883 \
-c 50000 -R 1000 -k 60 \
--ifaddr 10.0.0.11,10.0.0.12Kademeli artırın — örneğin 10k, 25k, 50k — ve her seviyeyi birkaç dakika tutun. 50.000 bağlantıyı kabul edip bir sonraki keep-alive döngüsünde düşürmeye başlayan bir broker testi geçmiş sayılmaz.
Değiştirebileceğiniz bir Node.js betiği
Gerçek kimlik doğrulama akışlarına, istemci başına aboneliklere veya özel client ID'lere ihtiyacınız olduğunda, küçük bir MQTT.js 5 betiğini uyarlamak bir benchmark aracından daha kolaydır:
import mqtt from "mqtt";
const URL = process.env.MQTT_URL ?? "mqtt://broker.connectmq.com:1883";
const TOTAL = Number(process.argv[2] ?? 100); // varsayılan: küçük bir smoke test
const RATE = Number(process.argv[3] ?? 200); // saniyedeki yeni bağlantı sayısı
let opened = 0, up = 0, errors = 0, closes = 0;
function open(i) {
const c = mqtt.connect(URL, {
clientId: `stress-${process.pid}-${i}`,
username: process.env.MQTT_USER,
password: process.env.MQTT_PASS,
keepalive: 60,
connectTimeout: 15_000,
reconnectPeriod: 2000 + Math.floor(Math.random() * 8000), // istemci başına jitter
});
let online = false;
c.on("connect", () => {
if (!online) { online = true; up++; }
c.subscribe(`testmqtt/stress/${i}/cmd`, { qos: 1 });
});
c.on("close", () => { if (online) { online = false; up--; } closes++; });
c.on("error", () => errors++);
}
const timer = setInterval(() => {
for (let k = 0; k < RATE / 10 && opened < TOTAL; k++) open(opened++);
if (opened >= TOTAL) clearInterval(timer);
}, 100);
setInterval(() => {
console.log(`${new Date().toISOString()} opened=${opened} connected=${up} closes=${closes} errors=${errors}`);
}, 1000);npm install mqtt@5
ulimit -n 100000
MQTT_URL="mqtts://$MQTT_HOST:8883" node conn-stress.mjs 20000 300Tek bir Node.js süreci birkaç bin boştaki bağlantıyı rahatça tutar; daha fazlası için birden çok süreç veya makine çalıştırın. Yük üretecinin CPU'sunu izleyin — tavan yaptıysa sayılarınız broker'ı değil, istemciyi ölçüyordur. Broker'ın reddedilen bağlantılara verdiği yanıtı yorumlamak için CONNACK kodunu reason code referansında arayın.
Broker tarafını izleyin
İstemci tarafındaki sayaçlar hikâyenin yalnızca yarısını anlatır. Her kademede broker host'unda şunları kaydedin:
ss -s # soket özeti
ss -tn state established '( sport = :1883 )' | wc -l
ps -o rss=,pcpu= -p "$(pgrep -d, mosquitto)" # broker sürecinin belleği (KB) ve CPU'suMosquitto ayrıca $SYS/broker/clients/connected yayınlar; buna online istemci ile veya mosquitto_sub -t '$SYS/broker/clients/connected' -v ile abone olun — bkz. MQTT $SYS topic'leri. Broker host'unun da aynı dosya tanımlayıcısı payına ihtiyaç duyduğunu unutmayın: systemd altındaki Mosquitto için servise bir drop-in ile LimitNOFILE= ayarlayın ve mosquitto.conf içindeki max_connections değerini kontrol edin (Mosquitto yapılandırma üreteci bir başlangıç dosyası oluşturabilir). Yalnızca broker log'larında görünen hatalar çok fazla bağlantı yazısında ele alınıyor.
Bağlantı başına bellek kolayca hesaplanır: (N bağlantıdaki RSS − boştaki RSS) ÷ N. Bunu TLS ile ve TLS olmadan, gerçek abonelik sayınızla ölçün; çünkü her ikisi de sonucu değiştirir.
Bir yeniden bağlanma fırtınası simüle edin
50.000 boştaki istemciyi tutmak işin kolay kısmıdır. Tehlikeli an, hepsinin aynı anda yeniden bağlandığı andır — bir broker yeniden başlatmasından, bir load balancer failover'ından veya bölgesel kısa bir ağ kesintisinden sonra. Bu; bağlantı hızını, TLS handshake kapasitesini ve kimlik doğrulama backend'inin kapasitesini aynı anda test eder.
Kendi broker'ınızda bunu tetiklemenin iki yolu:
- Stres betiği bağlantıları tutarken broker'ı yeniden başlatın ve
connected=değerinin yeniden yükselişini izleyin. - Yük üreteci ile broker arasındaki ağı keep-alive süresinden uzun süre kesin (örneğin bir iptables kuralıyla veya Toxiproxy ile), ardından geri açın.
Tam bağlantı sayısına dönmenin ne kadar sürdüğünü ve bu sırada kaç denemenin başarısız olduğunu kaydedin. Sabit bir yeniden bağlanma aralığıyla tüm istemciler aynı anda yeniden dener ve broker senkronize dalgalarla karşılaşır. Yukarıdaki betikteki jitter'lı reconnectPeriod bu dalgaları yayar; iki varyantı karşılaştırdığınızda yeniden bağlanma fırtınalarının neden broker kapasitesi kadar istemci tasarımı sorunu olduğunu göreceksiniz.
Bağlantı stres testi kontrol listesi
- Her yük makinesinde
ulimit -ndeğerini yükseltin,ip_local_port_rangearalığını genişletin ve conntrack'i kontrol edin. - Kaynak IP'leri planlayın: broker uç noktası başına, kaynak IP başına yaklaşık 64.000 bağlantı.
- Production'ı taklit edin: TLS, keep-alive, kimlik doğrulama ve istemci başına abonelikler.
- Kademeli artırın ve her kademeyi birkaç keep-alive aralığı boyunca tutun.
- Her kademede broker bağlantılarını, belleği, CPU'yu ve bağlantı gecikmesini kaydedin.
- Bir yeniden bağlanma fırtınası tetikleyin ve toparlanma süresini ölçün.
- Broker güncellemelerinden veya yapılandırma değişikliklerinden sonra tekrarlayın.
Bir bağlantı stres testi büyük ölçüde dürüstlük meselesidir: kendi tarafınızdaki limitleri kaldırın, gerçek istemci davranışını yansıtın ve tavanın nerede olduğunu yük üreteci değil broker gösterene kadar zorlayın. Ardından filonuzu bu tavanın rahatça altında planlayın ve istemcilerinizin jitter ile yeniden bağlandığından emin olun ki bu tavan asla kazara test edilmesin.
Sıkça sorulan sorular
MQTT bağlantı testim neden yaklaşık 28.000 istemcide duruyor?
Bu genellikle yük üretecinin geçici (ephemeral) portlarının tükenmesidir: Linux varsayılan olarak tek bir kaynak IP'den aynı broker IP'si ve portuna yapılan bağlantılar için yaklaşık 28.000 yerel port kullanır. net.ipv4.ip_local_port_range aralığını genişletin veya daha fazla kaynak IP ekleyin.
Bir MQTT broker kaç bağlantıyı kaldırabilir?
Broker'a, belleğe, CPU'ya, TLS'e, keep-alive süresine ve mesaj trafiğine bağlıdır; evrensel bir sayı yoktur. Ölçün: broker'ın belleğini ve CPU'sunu kaydederken bağlantıları kademeli artırın ve bağlantı gecikmesinin ya da hataların yükseldiği noktayı bulun.
Herkese açık bir MQTT broker'a stres testi yapabilir miyim?
Hayır. Paylaşılan herkese açık bir broker'a binlerce bağlantı açmak onu herkes için yavaşlatır ve sizin sınırlanmanıza ya da engellenmenize yol açar. Bağlantı stres testlerini yalnızca kendi broker'larınıza veya bu amaçla sağlanmış instance'lara karşı yapın.

