Testes de brokers

Teste de carga de broker MQTT: meça throughput e latência

Como fazer teste de carga em um broker MQTT: meça mensagens por segundo, limites de conexões e latência p99 com emqtt-bench, mqtt-benchmark e Python.

Atualizado · 9 min de leitura

Teste de carga de broker MQTT: meça throughput e latência

Um broker que funciona com um cliente de teste ainda pode cair com mil dispositivos. Fazer teste de carga em um broker MQTT responde três perguntas antes que a produção responda: quantas conexões simultâneas ele aceita, quantas mensagens por segundo consegue rotear e qual latência seus subscribers veem enquanto ele está ocupado.

Este guia mostra como planejar um benchmark, executá-lo com duas ferramentas open source e um script Python, e ler os números sem se enganar.

O que medir

MétricaO que ela mostraMeta típica
Taxa de conexãoQuão rápido o broker aceita novos CONNECT (tempestades de reconexão!)Centenas por segundo
Conexões simultâneasLimites de memória e de descritores de arquivoTamanho da sua frota × 1,5
Throughput de publicaçãoMensagens por segundo aceitas dos publishersTráfego de pico × 2
Throughput de fan-outMensagens por segundo entregues aos subscribersDepende do design de topics
Latência de ponta a ponta (p50 / p99)Tempo entre a publicação e a entregap99 abaixo de 50 ms na região
Taxa de errosDesconexões, mensagens QoS 0 descartadas, timeoutsPróxima de zero

Faça sempre o benchmark com o mesmo QoS, tamanho de payload e estrutura de topics que seus dispositivos usam. Um teste que publica mensagens QoS 0 de 10 bytes em um único topic não diz nada sobre telemetria QoS 1 de 2 KB espalhada por 50.000 topics. Veja níveis de QoS no MQTT para entender como cada nível muda a quantidade de pacotes.

Escolha o alvo certo

Nunca rode um benchmark pesado contra um sandbox público compartilhado: os números não significam nada (você está competindo com todos os outros usuários) e os operadores vão limitar ou bloquear você. Faça ali um smoke test e depois aponte a carga para uma instância que você controla.

Nos exemplos abaixo usamos broker.connectmq.com; substitua host, porta e credenciais pelos da sua própria instância.

1. emqtt-bench

O emqtt-bench é uma ferramenta em Erlang capaz de abrir dezenas de milhares de conexões a partir de uma única máquina. O jeito mais fácil de executá-lo é com Docker:

Teste de conexões — 2.000 clientes a 200/s
docker run --rm -it emqx/emqtt-bench conn \
  -h broker.connectmq.com -p 1883 \
  -c 2000 -R 200 \
  -u "$MQTT_USER" -P "$MQTT_PASS"

Depois meça o throughput com um grupo de subscribers e um grupo de publishers rodando ao mesmo tempo:

Terminal 1 — 100 subscribers
docker run --rm -it emqx/emqtt-bench sub \
  -h broker.connectmq.com -p 1883 \
  -c 100 -t 'bench/%i/#' -q 1
Terminal 2 — 100 publishers, 1 mensagem a cada 10 ms cada um
docker run --rm -it emqx/emqtt-bench pub \
  -h broker.connectmq.com -p 1883 \
  -c 100 -I 10 -t 'bench/%i/data' -s 256 -q 1

%i é expandido para o índice do cliente, então cada publisher tem seu próprio topic e seu próprio subscriber: um padrão realista de telemetria um para um. 100 publishers × 100 msg/s dão uma meta de 10.000 mensagens por segundo. O emqtt-bench imprime as taxas de envio e recebimento a cada segundo; se a taxa recebida ficar atrás da enviada, o gargalo é o broker (ou a sua rede).

2. mqtt-benchmark (Go)

Se você prefere um único binário, o mqtt-benchmark publica um número fixo de mensagens e reporta estatísticas de throughput e latência:

Instalar e executar
go install github.com/krylovsk/mqtt-benchmark@latest

mqtt-benchmark \
  --broker tcp://broker.connectmq.com:1883 \
  --clients 50 --count 1000 --size 512 --qos 1 \
  --topic bench/go --format text

O resumo no final inclui mensagens por segundo por cliente, a taxa agregada e a média / desvio padrão dos tempos de publicação: uma forma rápida de comparar dois brokers ou duas configurações.

3. Um script de latência confiável

Ferramentas de throughput medem a rapidez com que as mensagens entram. Os usuários sentem a rapidez com que elas saem. Este script Python (paho-mqtt 2.x) inclui o horário de envio em cada payload e calcula os percentis de ponta a ponta no lado do subscriber:

latency.py
import json, statistics, time, uuid
import paho.mqtt.client as mqtt

HOST, PORT = "broker.connectmq.com", 1883
TOPIC = f"bench/{uuid.uuid4().hex[:8]}/latency"
N, RATE = 2000, 200          # mensagens, mensagens por segundo
samples = []

def on_message(client, userdata, msg):
    sent = json.loads(msg.payload)["t"]
    samples.append((time.perf_counter() - sent) * 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.connect(HOST, PORT)
pub.loop_start()
time.sleep(1)                # espera a assinatura se estabilizar

for i in range(N):
    pub.publish(TOPIC, json.dumps({"i": i, "t": time.perf_counter()}), qos=1)
    time.sleep(1 / RATE)

time.sleep(3)
samples.sort()
p = lambda q: samples[int(len(samples) * q) - 1]
print(f"received {len(samples)}/{N}")
print(f"p50 {p(0.50):.1f} ms  p95 {p(0.95):.1f} ms  p99 {p(0.99):.1f} ms  max {samples[-1]:.1f} ms")
print(f"mean {statistics.mean(samples):.1f} ms")

Como publisher e subscriber rodam no mesmo processo, eles compartilham um único relógio: não há desvio de NTP no resultado. Rode uma vez com o broker ocioso e outra enquanto o emqtt-bench o castiga: a diferença é a latência que seus dispositivos vão ver no pico.

Como ler os resultados

  • Recebidas < enviadas em QoS 0 significa que o broker ou o cliente descartou mensagens sob pressão. Repita com QoS 1 para ver se é um problema de entrega ou de capacidade.
  • p99 muito acima do p50 indica pausas de garbage collection, persistência em disco ou um link de rede saturado. Verifique a CPU do broker e a do gerador de carga: uma máquina de benchmark no limite é o falso resultado mais comum.
  • O teste de conexões trava em um número redondo (1.024, 4.096, 65.535): você atingiu um limite de descritores de arquivo ou de portas efêmeras no gerador de carga, não no broker. Aumente o ulimit -n ou distribua a carga entre várias máquinas ou IPs de origem.
  • Desconexões durante o teste: procure timeouts de keep alive ou os limites de inflight / fila por cliente do broker. Veja keep alive no MQTT e erros de conexão.

Checklist repetível de teste de carga

  1. Faça primeiro um smoke test de conectividade com o cliente MQTT online ou com mosquitto_pub / mosquitto_sub.
  2. Fixe o cenário: número de clientes, QoS, tamanho de payload, estrutura de topics, retained ou não.
  3. Aumente a carga gradualmente (10 %, 50 %, 100 %, 150 % do pico esperado) e mantenha cada etapa por alguns minutos.
  4. Registre CPU, memória e número de conexões do broker ao lado dos números do lado do cliente.
  5. Repita o teste duas vezes; confie apenas em resultados que se reproduzem.
  6. Rode de novo após cada atualização ou mudança de configuração do broker.

Faça primeiro um smoke test do broker no navegador

O teste de carga transforma "funciona no meu notebook" em um número com o qual você pode planejar capacidade. Comece pequeno, meça a latência onde seus usuários estão e mantenha os scripts no seu repositório para que o próximo benchmark leve minutos em vez de dias.

Perguntas frequentes

Posso fazer teste de carga em um broker MQTT público?

Só de forma leve. Sandboxes públicos são compartilhados e têm limite de taxa, e tráfego pesado degrada o serviço para todos os outros. Faça testes de carga reais em um broker seu ou em uma instância privada destinada a testes.

Qual é uma boa latência MQTT?

Na mesma região, um broker saudável entrega mensagens QoS 0 de ponta a ponta em poucos milissegundos e QoS 1 em menos de 20 ms sob carga moderada. Acompanhe o p99, não a média: são os picos que quebram os dispositivos.

Qual é a melhor ferramenta para benchmarks MQTT?

O emqtt-bench é a opção open source mais completa para carga de conexões, publicação e assinatura. O mqtt-benchmark (Go) é mais simples de instalar. Um script próprio pequeno é o melhor quando você precisa dos seus payloads e da sua estrutura de topics exatos.