O monitoramento externo de uptime responde a uma única pergunta: um dispositivo fora da sua rede conseguiria, agora, conectar ao broker e trocar uma mensagem? Métricas internas não respondem isso. Elas não veem falhas de DNS, certificados expirados, load balancers quebrados nem uma mudança no firewall. Só uma sonda que se comporta como um cliente e roda de fora consegue ver.
Este guia constrói essa sonda, agenda a execução, envia alertas para o Slack ou o PagerDuty e mostra a matemática de SLO necessária para escolher o intervalo das verificações e o limite de alerta.
O que "no ar" significa para um broker MQTT
"A porta está aberta" é uma definição fraca. Um broker só é útil quando todas estas camadas funcionam:
| Camada | Verificação | Falha típica que detecta |
|---|---|---|
| DNS | O hostname resolve | Domínio expirado, registro errado após uma migração |
| TCP | A porta 8883 aceita a conexão | Firewall, security group, processo do broker parado |
| TLS | Handshake funciona e o certificado vale por mais N dias | Certificado expirado ou que não confere |
| MQTT CONNECT | CONNACK com código de sucesso | Backend de autenticação fora do ar, credenciais trocadas, limite de conexões atingido |
| Ida e volta | Mensagem publicada recebida dentro do tempo limite | Roteamento quebrado, cluster dividido, sobrecarga |
Verifique cada camada separadamente e informe qual delas falhou. "TLS falhou, certificado expirado" se resolve em cinco minutos. "A sonda falhou" inicia uma investigação de meia hora. Para verificações manuais pontuais, veja verificar o status de um broker MQTT e testar se uma porta MQTT está aberta.
Uma sonda mínima com os clientes do Mosquitto
Se você já tem mosquitto_pub e mosquitto_sub, uma sonda em shell cabe em uma dúzia de linhas:
#!/usr/bin/env bash
set -u
HOST=broker.connectmq.com; PORT=8883
TOPIC="testmqtt/uptime/$(hostname)-$$"
MSG="ping-$(date +%s)"
OUT=$(mktemp)
mosquitto_sub -h "$HOST" -p "$PORT" --capath /etc/ssl/certs \
-u "$MQTT_USER" -P "$MQTT_PASS" -t "$TOPIC" -q 1 -C 1 -W 10 > "$OUT" &
SUB=$!
sleep 1
mosquitto_pub -h "$HOST" -p "$PORT" --capath /etc/ssl/certs \
-u "$MQTT_USER" -P "$MQTT_PASS" -t "$TOPIC" -q 1 -m "$MSG"
wait $SUB
if grep -qx "$MSG" "$OUT"; then echo "OK"; rm -f "$OUT"; exit 0
else echo "FAIL: no round trip within 10 s"; rm -f "$OUT"; exit 1; fi-C 1 faz o assinante encerrar após uma mensagem, e -W 10 faz com que ele desista depois de dez segundos. O código de saída é tudo de que um agendador ou um serviço de heartbeat precisa.
Uma sonda em camadas com Python
Esta versão (paho-mqtt 2.x) verifica cada camada, mede o tempo, informa quantos dias faltam para o certificado expirar e imprime uma linha JSON fácil de mandar para os logs:
import json, os, socket, ssl, sys, threading, time, uuid
import paho.mqtt.client as mqtt
HOST, PORT, TIMEOUT = "broker.connectmq.com", 8883, 10
result = {"host": HOST, "ts": int(time.time())}
def fail(stage, detail):
result.update(ok=False, stage=stage, detail=str(detail))
print(json.dumps(result)); sys.exit(1)
t = time.perf_counter()
try:
socket.getaddrinfo(HOST, PORT)
except OSError as e:
fail("dns", e)
try:
ctx = ssl.create_default_context()
with socket.create_connection((HOST, PORT), timeout=TIMEOUT) as raw:
with ctx.wrap_socket(raw, server_hostname=HOST) as tls:
not_after = ssl.cert_time_to_seconds(tls.getpeercert()["notAfter"])
except ssl.SSLError as e:
fail("tls", e)
except OSError as e:
fail("tcp", e)
result["cert_days_left"] = int((not_after - time.time()) // 86400)
result["tls_ms"] = round((time.perf_counter() - t) * 1000)
topic = f"testmqtt/uptime/{uuid.uuid4().hex[:8]}"
connack, got = {}, threading.Event()
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"testmqtt-uptime-{uuid.uuid4().hex[:6]}")
c.username_pw_set(os.getenv("MQTT_USER"), os.getenv("MQTT_PASS"))
c.tls_set_context(ctx)
c.on_connect = lambda cl, ud, fl, rc, pr: (connack.update(rc=rc),
None if rc.is_failure else cl.subscribe(topic, qos=1))
c.on_subscribe = lambda cl, ud, mid, rcs, pr: cl.publish(topic, "ping", qos=1)
c.on_message = lambda cl, ud, msg: got.set()
t = time.perf_counter()
try:
c.connect(HOST, PORT, keepalive=15)
except OSError as e:
fail("connect", e)
c.loop_start()
ok = got.wait(TIMEOUT)
c.disconnect(); c.loop_stop()
if "rc" not in connack:
fail("connect", "no CONNACK")
if connack["rc"].is_failure:
fail("connect", connack["rc"])
if not ok:
fail("roundtrip", f"no message within {TIMEOUT} s")
result.update(ok=True, roundtrip_ms=round((time.perf_counter() - t) * 1000))
print(json.dumps(result))
sys.exit(2 if result["cert_days_left"] < 14 else 0)Código de saída 0 significa saudável, 1 significa fora do ar (o campo stage diz onde) e 2 significa no ar, mas com o certificado expirando em menos de duas semanas. Esse último é um aviso, não um chamado de plantão. Quando a etapa connect falha, o reason code (por exemplo Not authorized) mostra se o problema é de credencial ou de ACL. Consulte-o na ferramenta de reason codes ou em erros de conexão MQTT.
Agendando a sonda
- cron ou um timer do systemd em uma VM pequena fora da rede do broker:
* * * * * /opt/probe/mqtt_uptime_probe.py >> /var/log/mqtt-probe.log 2>&1. É simples e roda a cada minuto. - Vários locais. Rode a mesma sonda a partir de duas ou três regiões ou provedores. Alerte quando a maioria falhar. Se só um local falha, geralmente o problema é a rede daquele local.
scheduledo GitHub Actions serve para verificações pouco críticas, mas o intervalo mínimo é de cinco minutos e as execuções podem começar atrasadas. Não serve para acionar plantão.- Uptime Kuma (self-hosted) tem um tipo de monitor MQTT e funciona bem se você prefere uma interface gráfica.
O que roda a sonda também pode falhar. Use um heartbeat (dead man's switch): depois de cada execução bem-sucedida, a sonda faz ping em uma URL de um serviço de heartbeat, como o Healthchecks.io ou um push monitor do Uptime Kuma. Se os pings param, o broker ou a máquina da sonda caiu, e você recebe um alerta nos dois casos:
* * * * * /opt/probe/mqtt-probe.sh && curl -fsS -m 10 --retry 3 "$HEARTBEAT_URL" > /dev/nullCanais de alerta
Mande alertas para onde alguém realmente vai vê-los, e só depois de evidência suficiente. Uma regra comum é três falhas consecutivas, de pelo menos dois locais, com mensagem de recuperação quando o problema passa.
curl -fsS -X POST -H 'Content-Type: application/json' \
-d '{"text":":red_circle: MQTT probe failed at stage tls (broker.connectmq.com:8883)"}' \
"$SLACK_WEBHOOK_URL"curl -fsS -X POST https://events.pagerduty.com/v2/enqueue \
-H 'Content-Type: application/json' \
-d '{"routing_key":"'"$PD_ROUTING_KEY"'","event_action":"trigger",
"dedup_key":"mqtt-probe-broker",
"payload":{"summary":"MQTT round trip failing","source":"mqtt-probe","severity":"critical"}}'Envie a mesma requisição com "event_action":"resolve" e a mesma dedup_key para fechar o incidente automaticamente. Deixe os avisos de expiração de certificado no Slack ou no e-mail. Eles exigem ação nesta semana, não às 3 da manhã. Se você já usa Prometheus, exporte a sonda como métricas e alerte por lá. Veja monitorar MQTT com Prometheus e Grafana.
Matemática de SLO
Uma meta de disponibilidade só faz sentido junto com o seu orçamento de indisponibilidade:
| Disponibilidade | Indisponibilidade por 30 dias | Indisponibilidade por ano |
|---|---|---|
| 99% | 7 h 12 min | 3,65 dias |
| 99,5% | 3 h 36 min | 1,83 dia |
| 99,9% | 43,2 min | 8 h 46 min |
| 99,95% | 21,6 min | 4 h 23 min |
| 99,99% | 4,3 min | 52,6 min |
Meça como sondas bem-sucedidas ÷ total de sondas. Uma sonda por minuto gera 43.200 amostras em 30 dias, então 99,9% permite 43 sondas com falha. Daí vêm três consequências:
- O intervalo limita a precisão. Com uma sonda por minuto, uma queda de 20 segundos pode passar despercebida ou contar como um minuto inteiro. Para medir 99,99%, sonde a cada 10–15 segundos.
- O tempo de detecção consome o orçamento. Três falhas com intervalo de um minuto significam cerca de três minutos até alguém ser acionado. Isso é aceitável para 99,9% (43 minutos) e é quase todo o orçamento em 99,99%.
- O seu SLO não é o SLA do provedor. O SLA cobre o broker. A sua sonda mede o caminho inteiro, incluindo seu DNS, seus certificados e sua rede. Leia SLA e uptime de brokers MQTT antes de comparar os dois.
Acompanhe o orçamento de erros: se no meio do mês 30 dos seus 43 minutos já foram gastos, congele mudanças arriscadas no broker até ele se recuperar.
Teste o caminho dos alertas
Uma sonda que nunca falhou não foi testada. Antes de depender dela:
- Coloque uma senha errada e confirme que a etapa
connectfalha e o alerta chega ao Slack ou ao PagerDuty. - Aponte
HOSTpara um nome que não resolve e confirmestage: dns. - Pare o cron e confirme que o serviço de heartbeat avisa você.
- Confira manualmente se o que a sonda vê corresponde à realidade: conecte-se com o cliente MQTT online e publique no tópico da sonda enquanto ela roda.
O monitoramento externo de uptime é um pequeno script, um agendador e um heartbeat. Verifique cada camada separadamente, alerte só com falhas repetidas vindas de mais de um local, escolha o intervalo da sonda a partir do seu SLO e quebre a configuração de propósito uma vez para provar que os alertas chegam.
Perguntas frequentes
Verificar se a porta 1883 está aberta é suficiente para monitorar o uptime MQTT?
Não. Um broker pode aceitar conexões TCP e, ao mesmo tempo, recusar logins, falhar no TLS ou não rotear mensagens. Uma verificação real conecta com credenciais, assina um tópico, publica uma mensagem e confirma que ela chega dentro de um tempo limite.
Com que frequência uma sonda de uptime MQTT deve rodar?
A cada minuto é um bom padrão. O intervalo limita a precisão da medição: com uma verificação por minuto, quedas menores que um minuto podem passar despercebidas, e um orçamento mensal de 99,99% (cerca de quatro minutos) se esgota antes de um alerta de três falhas disparar.
Quanto tempo fora do ar 99,9% permite?
Cerca de 43 minutos por mês de 30 dias, ou aproximadamente 8 horas e 46 minutos por ano. 99,95% permite cerca de 22 minutos por mês, e 99,99% cerca de 4,3 minutos.


