Broker testleri

MQTT Benchmark Sonuçlarını Kendinizi Kandırmadan Okuma

MQTT benchmark sonuçlarını doğru yorumlayın: ortalamalar neden yanıltır, coordinated omission gecikmeyi nasıl gizler, darboğazlar nasıl bulunur ve raporlanır.

Güncellendi · 8 dk okuma

MQTT Benchmark Sonuçlarını Kendinizi Kandırmadan Okuma

Bir MQTT benchmark'ı çok hızlı sayı üretir. Güvenebileceğiniz sayılar üretmek ise daha zordur. Yanıltıcı sonuçların çoğu aynı birkaç hatadan doğar: ortalamaları aktarmak, broker yerine yük üreticiyi ölçmek, coordinated omission'ı görmezden gelmek ve aynı şekilde kurulmamış çalıştırmaları karşılaştırmak.

Bu rehber her tuzağı tek tek ele alıyor, kendi verilerinizde nasıl tespit edeceğinizi gösteriyor ve sonuçları tekrarlanabilir kılan bir rapor şablonuyla bitiyor. Halihazırda bir test çalıştırdığınızı varsayıyoruz; çalıştırmadıysanız MQTT broker yük testi ile başlayın.

Ortalamalar yavaş mesajları gizler

Gecikme hiçbir zaman normal dağılmaz. Yük altındaki bir broker mesajların çoğunu birkaç milisaniyede, küçük bir kısmını ise yüzlerce milisaniyede teslim eder — bir garbage collection duraklaması, diske yazma ya da yeniden iletim sırasında. Ortalama iki grubu karıştırıp hiçbirini anlatmayan bir sayı üretir.

ÇalıştırmaOrtalamap50p99Maks.
A6 ms4 ms12 ms30 ms
B6 ms3 ms140 ms900 ms

(Örnek değerler.) İki çalıştırmanın ortalaması aynı, ama B'de her yüz mesajdan biri saniyenin onda birinden fazla gecikmeyle ulaşıyor. Saniyede bir publish yapan bir cihaz için bu, yaklaşık her iki dakikada bir fark edilir bir gecikme demektir.

Sizi dürüst tutan kurallar:

  • Yüzdelikleri raporlayın: p50 (tipik), p99 (kuyruk), maks. (gözlemlenen en kötü durum). p99.9'u yalnızca yeterli örneğiniz varsa ekleyin.
  • Yüzdeliklerin asla ortalamasını almayın. On p99 değerinin ortalaması, birleşik verinin p99'u değildir — ham örnekleri ya da histogramları birleştirin.
  • Örnek sayısını kontrol edin. 100 mesajın p99'u tek bir mesajdır. Her çalıştırmada binlerce örnek toplayın.

Coordinated omission

Coordinated omission, bir benchmark'ın gerçekte olduğundan iyi görünmesinin en yaygın nedenidir. Yük üretici bir sonraki isteği göndermeden önce yanıtı beklediğinde ortaya çıkar. Broker 500 ms takılırsa, senkron çalışan bir publisher bir yavaş mesaj kaydeder — ve gerçek bir filonun o yarım saniyede göndereceği diğer 49 mesajı hiç göndermez. Hepsi yüksek gecikme görecek olan bu mesajlar verilerde hiç yer almaz.

Gerçek cihazlar broker ile koordine olmaz. Bir sensör, son PUBACK gelmiş olsun ya da olmasın kendi takvimine göre publish eder. Bunu yeniden üretmek için gecikmeyi mesajın sokete gerçekten verildiği andan değil, planlanan gönderim zamanından itibaren ölçün:

intended_time.py — latency without coordinated omission
import json, statistics, time, uuid
import paho.mqtt.client as mqtt

HOST, PORT = "broker.connectmq.com", 1883
TOPIC = f"testmqtt/bench-{uuid.uuid4().hex[:8]}/latency"
N, RATE = 20000, 500                   # mesaj sayısı, saniyedeki mesaj
samples = []

def on_message(client, userdata, msg):
    intended = json.loads(msg.payload)["t"]
    samples.append((time.perf_counter() - intended) * 1000)

sub = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
sub.on_message = on_message
sub.connect(HOST, PORT)
sub.subscribe(TOPIC, qos=1)
sub.loop_start()

pub = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
pub.max_queued_messages_set(0)         # 0 = istemci tarafında sınırsız kuyruk
pub.connect(HOST, PORT)
pub.loop_start()
time.sleep(1)

start = time.perf_counter()
for i in range(N):
    intended = start + i / RATE        # gerçek bir cihazın izleyeceği takvim
    delay = intended - time.perf_counter()
    if delay > 0:
        time.sleep(delay)
    pub.publish(TOPIC, json.dumps({"i": i, "t": intended}), qos=1)

time.sleep(5)
q = statistics.quantiles(samples, n=1000)   # 999 kesim noktası
print(f"received {len(samples)}/{N}")
print(f"p50 {q[499]:.1f} ms  p99 {q[989]:.1f} ms  p99.9 {q[998]:.1f} ms  max {max(samples):.1f} ms")

Publisher takvimin gerisine düşerse — broker ya da ağ geri ittiği için — gecikmeli her mesaj bu gecikmeyi kendi ölçümünde taşır. Çıktıyı, publish anında time.perf_counter() damgası basan bir sürümle karşılaştırın: planlanan zamana göre p99 çok daha yüksekse, broker takılıyordu ve basit ölçüm bunu gizliyordu.

Broker'ı mı ölçüyorsunuz, istemciyi mi?

CPU'su, soketleri ya da ağ bant genişliği tükenen bir benchmark makinesi, tıpatıp broker limitine benzeyen bir plato üretir. Broker'ı suçlamadan önce yük üreticiyi kontrol edin:

  • Üreticinin CPU'su. Bir çekirdek %100'de duruyorsa (tek iş parçacıklı istemcilerde sık görülür; örneğin saniyede yüzlerce mesajı tek bir paho ağ döngüsünün işlemesi), tavan sizin tarafınızdadır. İstemcileri birden fazla süreç ya da makineye dağıtın.
  • Yuvarlak sayılarda platolar. 1.024, 4.096 veya 28.000–64.000 civarında duran bağlantı sayıları genellikle istemci makinesindeki dosya tanımlayıcı ya da geçici (ephemeral) port limitlerine işaret eder. ulimit -n değerini artırın veya kaynak IP ekleyin.
  • Ağ arayüzü. Mesaj hızını hattaki boyutla çarpın (paket boyutu hesaplayıcı PUBLISH başına tam bayt sayısını verir) ve TLS ek yükü dahil bağlantı kapasitesiyle karşılaştırın.
  • İki makine testi. Aynı yükü, her biri yarı hızda olan iki üreticiden gönderin. Toplam throughput artıyorsa darboğaz tek üreticiydi.

Hikâyenin geri kalanını broker tarafı anlatır: CPU, bellek, bağlantı sayısı ve mesaj hızlarını (örneğin $SYS topic'lerinden ya da Prometheus'tan) istemci tarafı sayıların yanına kaydedin. %30 CPU'da çalışıp throughput grafiği kilitlenmiş bir broker başka bir şeyi bekliyordur.

Saatler, ısınma ve diğer sessiz bozulmalar

  • Saat kayması. Publisher ve subscriber farklı makinelerde çalışıyorsa, uçtan uca gecikme saatleri arasındaki farkı da içerir. NTP saatleri en iyi ihtimalle birkaç milisaniye içinde tutar — çoğu zaman daha kötü. Publisher ve subscriber'ı tek süreçte çalıştırarak ölçün ya da gidiş-dönüş süresi kullanın. Ayrıntılar: MQTT saat ve zaman damgası sorunları.
  • Isınma. İlk saniyeler TCP ve TLS el sıkışmalarını, JIT derlemeyi ve önbellek ıskalarını içerir. Bir ısınma süresini atın ya da ayrı raporlayın.
  • Çok kısa çalıştırmalar. 30 saniyelik bir çalıştırma, kalıcılık anlık görüntüleri veya log rotasyonu gibi periyodik olayları kaçırabilir. Her yük seviyesini dakikalarca tutun; saatler için bir soak testi kullanın.
  • Kaybolan mesajlar. Yalnızca ulaşan mesajlardan hesaplanan yüzdelikler, yavaş olanlar düşürüldüyse harika görünür. Gecikmenin yanında her zaman alınan / gönderilen oranını raporlayın.
  • Farklı QoS. QoS 0, 1 ve 2'nin paket sayıları ve maliyetleri çok farklıdır; sonuçları QoS seviyeleri arasında aynı testmiş gibi asla karşılaştırmayın. Bkz. QoS 0 vs 1 vs 2 benchmark.

Kötü bir sonucu tanımak

Verideki belirtiOlası nedenNasıl doğrulanır
Broker CPU'su düşükken throughput sabitYük üretici doymuşÜreticinin CPU'suna bakın; iki üreticiyle tekrarlayın
QoS 0'da alınan < gönderilenİstemci ya da broker baskı altında mesaj düşürüyorQoS 1 ile tekrarlayıp sayıları karşılaştırın
p99 iyi, maks. çok büyükTek bir takılma (GC, failover, disk)Sadece histogram değil, gecikmeyi zamana göre çizin
p50 çalıştırma boyunca sürekli artıyorKuyruk birikiyor (yavaş tüketici)Broker'ın kuyruk / inflight metriklerini izleyin
Aynı çalıştırmalar arasında %30 farkPaylaşımlı veya gürültülü ortamÜç kez çalıştırın; izole bir broker'da test edin
Negatif ya da imkânsız derecede düşük gecikmeFarklı makinelerin saatleriTek süreç içinde ölçün

MQTT benchmark sonuçları nasıl raporlanır

Kurulumu belirtilmemiş bir sayı ne tekrarlanabilir ne karşılaştırılabilir. En azından şunları raporlayın:

AlanÖrnek
Broker, sürüm, dağıtımBroker X 2.x, 4 vCPU / 8 GB, tek node
İstemci aracı ve sürümüemqtt-bench / paho-mqtt 2.x ile özel script
Yük üretici2 makine, aynı bölge, CPU zirvesi %55
Ağ ve taşımaAynı bölge, TCP 1883 (veya TLS 8883)
Protokol ve QoSMQTT 5, QoS 1, clean start
İş yükü1.000 publisher, her biri 1 msg/s, 512 B JSON, 1:1 topic'ler
Süre5 dk ısınma hariç, 20 dk ölçüm
SonuçlarGönderilen/alınan throughput, p50, p99, p99.9, maks., hatalar
Ham veriHistogram veya CSV bağlantısı

İki alışkanlık raporları çok daha faydalı kılar:

  1. Gecikmeyi zamana göre çizin. Histogram, yavaş mesajların ne zaman yaşandığını gizler. Zaman serisi ise kuyruğun sabit bir özellik mi yoksa birkaç olaydan mı ibaret olduğunu gösterir.
  2. Doyma noktasını gösterin. Tek bir sayı yerine artan yük seviyeleri çalıştırın ve p99'un hedefinizi (örneğin 50 ms) aştığı hızı raporlayın. Kullanılabilir kapasiteniz bu hızdır; mutlak maksimum throughput değil.

Her çalıştırmadan önce hızlı bir kontrol

Uzun bir benchmark başlatmadan önce online MQTT istemcisi ile bağlanın, test topic'inize abone olun ve elle birkaç mesaj publish edin. Bir mesaj gözle görülür şekilde geç geliyorsa ya da abonelik hiçbir şey almıyorsa önce bunu düzeltin — yük testi size bundan fazlasını söylemeyecektir.

Benchmark topic'inizi tarayıcıda test edin

Benchmark'lar ancak arkalarındaki sorular kadar iyidir. Planlanan gönderim zamanından ölçün, yük üreticiyi gözden kaçırmayın, yüzdelikleri teslim sayıları ve tam kurulumla birlikte raporlayın; MQTT sayılarınız onları yeniden üretmeye çalışan bir sonraki kişiye — gelecekteki kendiniz dahil — dayanacaktır.

Sıkça sorulan sorular

MQTT benchmark'ında ortalama gecikme neden yanıltıcıdır?

Gecikme dağılımları çarpıktır: mesajların çoğu hızlı, birkaçı ise çok yavaştır. Ortalama iki grubu karıştırır ve cihazların ile kullanıcıların gerçekten fark ettiği yavaş kuyruğu gizler. Bunun yerine p50, p99 ve maksimumu raporlayın.

MQTT benchmark'ında coordinated omission nedir?

Yük üreticinin bir sonraki mesajı göndermeden önce yavaş bir yanıtı beklemesiyle oluşur. Takılma, o sürede gönderilmesi gereken her mesaj için değil yalnızca bir kez ölçülür; bu yüzden araç, gecikmeyi tam da broker zorlandığında olduğundan düşük gösterir.

Güvenilir bir p99 için kaç mesaj gerekir?

Her çalıştırmada en az birkaç bin örnek. 100 mesajda p99 tek bir örnektir. p99 için 10.000 veya daha fazlasını, p99.9 vermek istiyorsanız 100.000 veya daha fazlasını hedefleyin.