Prometheus ve Grafana, bir MQTT broker'ını izlemek için kullanılan yaygın ikilidir. Prometheus metrikleri HTTP üzerinden toplar ve alarm kurallarını değerlendirir. Grafana dashboard'ları çizer. Broker'lar metriklerini iki şekilde sunar: bazılarının yerel bir Prometheus endpoint'i vardır (EMQX, VerneMQ, bir extension aracılığıyla HiveMQ), Mosquitto gibi diğerleri ise yalnızca $SYS topic'leri yayınlar ve bunları çevirecek bir exporter'a ihtiyaç duyar.
Bu rehber büyük ihtimalle ihtiyaç duyacağınız üç veri kaynağını bağlar: Mosquitto için bir exporter, EMQX'in yerel endpoint'i ve yönetilen broker'lar dahil her broker'la çalışan istemci taraflı bir probe. Ardından dashboard'lar ve alarmlar eklenir.
Metrikler nereden gelir?
| Broker | Prometheus metrikleri nasıl alır |
|---|---|
| Mosquitto | mosquitto-exporter $SYS/# topic'ine abone olur ve /metrics sunar (varsayılan port 9234) |
| EMQX 5 | Dashboard/API portunda (18083) yerleşik /api/v5/prometheus/stats endpoint'i ya da bir Pushgateway'e gönderim |
| HiveMQ | HiveMQ Prometheus Monitoring Extension, /metrics sunar (varsayılan port 9399) |
| VerneMQ | HTTP listener'ında yerleşik /metrics (varsayılan port 8888) |
| Yönetilen broker | Sağlayıcı sunuyorsa onun metrikleri, ayrıca kendi istemci taraflı probe'unuz |
Broker tarafı metrikler broker'ın ne yaptığını anlatır: bağlantılar, throughput, kuyruklar ve düşürülen mesajlar. İstemci taraflı bir probe ise cihazlarınızın ne yaşadığını gösterir: bağlanabiliyorlar mı ve bir mesaj ne kadar sürüyor? İkisine de ihtiyacınız var. Yalnızca birini seçebiliyorsanız probe'u seçin, çünkü DNS, TLS, load balancer ve kimlik doğrulama hatalarını yakalayan odur.
$SYS sizin için yeniyse önce $SYS topic'leri ile broker izleme yazısını okuyun. Aşağıdaki exporter bunun üzerinde ince bir katmandır.
Docker Compose ile yerel bir stack
Bu stack Mosquitto'yu, exporter'ı, Prometheus'u ve Grafana'yı birlikte çalıştırır. Dashboard'ları production'a yönlendirmeden önce hazırlamak için iyi bir laboratuvardır.
services:
mosquitto:
image: eclipse-mosquitto:2
ports: ["1883:1883"]
volumes:
- ./mosquitto.conf:/mosquitto/config/mosquitto.conf:ro
mosquitto-exporter:
image: sapcc/mosquitto-exporter
command: ["--endpoint", "tcp://mosquitto:1883"]
ports: ["9234:9234"]
depends_on: [mosquitto]
prometheus:
image: prom/prometheus
ports: ["9090:9090"]
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./alerts.yml:/etc/prometheus/alerts.yml:ro
grafana:
image: grafana/grafana
ports: ["3000:3000"]
volumes:
- ./grafana-datasource.yml:/etc/grafana/provisioning/datasources/prometheus.yml:rolistener 1883
allow_anonymous true
sys_interval 10apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
isDefault: trueallow_anonymous true yalnızca dizüstü bilgisayarınızda kabul edilebilir. Gerçek bir broker'da yalnızca $SYS/# okuyabilen ayrı bir izleme kullanıcısı oluşturun ve bunu exporter'a --user ve --pass ile verin. mosquitto.conf oluşturucu listener ve kimlik doğrulama bloklarını sizin için hazırlayabilir. Daha fazla servis içeren daha kapsamlı bir laboratuvar için MQTT Docker Compose stack'i yazısına bakın.
Exporter her sayısal $SYS topic'ini, adı topic yolunu izleyen bir metriğe dönüştürür; örneğin $SYS/broker/clients/connected broker_clients_connected olur. Sorgu yazmadan önce sürümünüzün ürettiği tam adları görmek için http://localhost:9234/metrics adresini açın.
Her broker için bir probe exporter'ı
Bu Python exporter'ı (paho-mqtt 2.x ve prometheus_client) her 15 saniyede bir TLS üzerinden bağlanır, benzersiz bir topic'e abone olur, bir mesaj yayınlar ve mesajın geri gelmesini bekler. İşlemin başarılı olup olmadığını ve her adımın ne kadar sürdüğünü dışa aktarır:
import os, ssl, threading, time, uuid
import paho.mqtt.client as mqtt
from prometheus_client import Gauge, Histogram, start_http_server
HOST, PORT, INTERVAL = "broker.connectmq.com", 8883, 15
success = Gauge("mqtt_probe_success", "1 if the last connect/publish/receive cycle worked")
connect_s = Gauge("mqtt_probe_connect_seconds", "TCP + TLS + CONNACK time of the last probe")
roundtrip = Histogram("mqtt_probe_roundtrip_seconds", "Subscribe, publish and receive time",
buckets=(0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5))
def probe() -> bool:
topic = f"testmqtt/probe/{uuid.uuid4().hex[:8]}"
connected, received = threading.Event(), threading.Event()
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"testmqtt-probe-{uuid.uuid4().hex[:6]}")
c.username_pw_set(os.getenv("MQTT_USER"), os.getenv("MQTT_PASS"))
c.tls_set(cert_reqs=ssl.CERT_REQUIRED)
c.on_connect = lambda cl, ud, fl, rc, pr: connected.set() if not rc.is_failure else None
c.on_subscribe = lambda cl, ud, mid, rcs, pr: cl.publish(topic, "ping", qos=1)
c.on_message = lambda cl, ud, msg: received.set()
t0 = time.perf_counter()
try:
c.connect(HOST, PORT, keepalive=10)
c.loop_start()
if not connected.wait(5):
return False
connect_s.set(time.perf_counter() - t0)
t1 = time.perf_counter()
c.subscribe(topic, qos=1)
if not received.wait(5):
return False
roundtrip.observe(time.perf_counter() - t1)
return True
except OSError:
return False
finally:
c.disconnect()
c.loop_stop()
if __name__ == "__main__":
start_http_server(9105) # metrikler http://localhost:9105/metrics adresinde
while True:
success.set(1 if probe() else 0)
time.sleep(INTERVAL)Bağımlılıkları pip install paho-mqtt prometheus-client ile kurun. Her döngüde yeni bir bağlantı açmak bilinçli bir tercihtir: tıpkı yeniden başlayan bir cihaz gibi her seferinde DNS, TLS ve kimlik doğrulama da test edilir. Her çalıştırmada benzersiz bir client ID kullanın. Client ID oluşturucu yinelenen ID'lerin neden birbirini düşürdüğünü açıklar.
Scrape yapılandırması
global:
scrape_interval: 15s
rule_files: ["/etc/prometheus/alerts.yml"]
scrape_configs:
- job_name: mosquitto
static_configs:
- targets: ["mosquitto-exporter:9234"]
- job_name: mqtt-probe
static_configs:
- targets: ["host.docker.internal:9105"] # probe'un çalıştığı yer
- job_name: emqx
metrics_path: /api/v5/prometheus/stats
static_configs:
- targets: ["emqx:18083"]Kullanmadığınız job'ları kaldırın. Güncel EMQX sürümlerinde istatistik endpoint'i kimlik doğrulama isteyecek şekilde yapılandırılabilir. Bu durumda bir API key ve secret ile basic_auth ekleyin. EMQX'i yerelde denemek için Docker'da EMQX yazısına bakın. host.docker.internal Docker Desktop'ta çalışır. Linux'ta probe'u başka bir Compose servisi olarak çalıştırın.
Gerçek soruları yanıtlayan dashboard'lar
Faydalı bir MQTT dashboard'unda az panel olur ve her biri bir olay sırasında birinin soracağı bir soruyu yanıtlar:
| Panel | PromQL (örnek) |
|---|---|
| İstemciler bağlı mı? | broker_clients_connected veya sum(emqx_connections_count) |
| Saniyede gelen / giden mesaj | rate(broker_messages_received[5m]), rate(emqx_messages_sent[5m]) |
| Mesaj düşürüyor muyuz? | rate(broker_publish_messages_dropped[5m]) veya rate(emqx_messages_dropped[5m]) |
| Bir istemci şu an bağlanabiliyor mu? | mqtt_probe_success |
| Teslimat ne kadar yavaş? | histogram_quantile(0.99, sum by (le) (rate(mqtt_probe_roundtrip_seconds_bucket[10m]))) |
| Bağlanma süresi | mqtt_probe_connect_seconds |
Sayaçlarda rate() kullanın, ham sayaç değerini asla grafiğe dökmeyin. Probe panellerini en üste koyun, çünkü kullanıcıların gördüğünü onlar gösterir. grafana.com'da Mosquitto exporter'ı ve EMQX için topluluk dashboard'ları yayınlanmıştır. İyi bir başlangıç noktasıdırlar ama metrik adlarının exporter sürümünüzle eşleştiğini kontrol edin.
Alarm kuralları
groups:
- name: mqtt
rules:
- alert: MqttProbeFailing
expr: max_over_time(mqtt_probe_success[3m]) == 0
labels: { severity: page }
annotations:
summary: "No successful MQTT round trip for 3 minutes"
- alert: MqttProbeSlow
expr: histogram_quantile(0.99, sum by (le) (rate(mqtt_probe_roundtrip_seconds_bucket[10m]))) > 0.5
for: 10m
labels: { severity: ticket }
- alert: MqttClientsDropped
expr: broker_clients_connected < 0.7 * (broker_clients_connected offset 10m)
for: 2m
labels: { severity: page }
- alert: MqttExporterDown
expr: up{job="mosquitto"} == 0
for: 2m
labels: { severity: ticket }MqttClientsDropped klasik olay örüntüsünü yakalar: süresi dolan bir sertifika, bir ağ değişikliği ya da broker'ın yeniden başlaması sonrasında cihazların büyük bir kısmı aynı anda bağlantıyı kaybeder. page alarmlarını Alertmanager üzerinden nöbet kanalınıza, ticket alarmlarını daha sakin bir yere yönlendirin. Dış kontroller ve SLO hesapları için MQTT uptime izleme yazısına bakın.
İzlemenin kendisini test edin
Alarmlara güvenmeden önce her birini bilerek tetikleyin:
- Probe hatası:
MQTT_PASSdeğerini yanlış bir değerle değiştirin ve probe'u yeniden başlatın.mqtt_probe_success0'a düşmeli veMqttProbeFailingyaklaşık üç dakika içinde tetiklenmelidir. - İstemci düşüşü: bir grup test istemcisi bağlayın (bir cihaz simülatörü veya online istemcinin birkaç sekmesi), on dakika bekleyin ve sonra kapatın. Bağlı istemciler paneli buna göre düşmelidir.
- Exporter kapalı:
docker compose stop mosquitto-exporterkomutuMqttExporterDownalarmını tetiklemelidir. - Gecikme: bir network shaper ile gecikme ekleyin ya da probe değerlerini ayrı bir gecikme testi ile karşılaştırın.
Testte hiç tetiklenmemiş bir alarm, gerçek bir kesinti sırasında da tetiklenmeyebilir.
Prometheus ve Grafana, $SYS'in tek başına sunamadığı geçmişi, dashboard'ları ve alarmları sağlar. Broker metriklerini istemci taraflı bir probe ile birleştirin, dashboard'u küçük tutun ve her alarma güvenmeden önce onu bir kez test edin.
Sıkça sorulan sorular
Mosquitto'nun yerleşik bir Prometheus endpoint'i var mı?
Hayır. Mosquitto istatistiklerini $SYS topic'lerinde yayınlar. mosquitto-exporter gibi bir exporter $SYS/# topic'ine abone olur ve değerleri Prometheus'un toplayabileceği bir HTTP /metrics endpoint'inde sunar.
Yönetilen bir MQTT broker'ını Prometheus ile izleyebilir miyim?
Evet, istemci tarafından. Broker'ın yanına exporter kuramasanız bile bağlanan, publish eden ve bir mesaj alan küçük bir probe başarı ve gecikme metrikleri dışa aktarabilir. Çoğu zaman zaten en faydalı sinyal budur.
İlk olarak hangi durumlar için alarm kurmalıyım?
Üç alarmla başlayın: probe'un birkaç dakika boyunca başarısız olması, bağlı istemci sayısında ani düşüş ve sıfırın üzerinde düşürülen mesaj. Normal p99 değerinizi öğrendikten sonra gecikme alarmları ekleyin.


