Testes de carga

Testes de esforço do broker em duas bancadas — pela rede e por loopback — para separar o comportamento do próprio broker do ambiente. A seguir: método, tabelas completas e conclusões breves.

Baixar o relatório (PDF)

As bancadas

Data: 24 de julho de 2026 · Protocolo: MQTT 3.1.1 · Ferramenta: cliente de carga próprio cmd/loadtest construído sobre o codec do projeto, sem bibliotecas MQTT de terceiros.

Os testes foram feitos em duas bancadas para separar o comportamento do próprio broker da influência do ambiente: rede contra loopback, hardware modesto contra hardware potente.

Bancada A — pela redeBancada B — loopback
Processador do broker12 núcleos2× Xeon E5-2690 v4 a 2,6 GHz (28 núcleos / 56 threads)
Memória do broker16 GB128 GB
Endereço192.168.1.84:1883 (LAN)127.0.0.1:1883 (loopback)
Gerador de cargaMáquina separada na LANA mesma máquina do broker
Portas efêmeras do cliente16 384 (padrão)55 000 (ampliado)
Como ler a comparação. As bancadas não são equivalentes e respondem a perguntas diferentes. A bancada A mostra o funcionamento sobre uma rede com gerador dedicado. A bancada B elimina a rede (latência quase nula) e dá ao broker hardware potente, mas gerador e broker dividem os mesmos núcleos. Por isso latência e leque podem ser comparados diretamente, enquanto a ingestão não: na bancada B o cliente rouba núcleos do broker.

Resumo executivo

  • Latência. Pela rede, a latência ponta a ponta «publicador → broker → assinante» sob carga normal fica em torno de 1 ms; por loopback é de 73 µs (~16 vezes menor, sem a rede).
  • Conexões. Pela rede o broker sustentou 10 000 sessões sem falhas (além disso esbarramos no limite de portas do cliente). Em hardware potente por loopback: 30 000 sem falhas e ~41 000 numa tentativa de 50 000 (o limite de uma única máquina, não do broker).
  • Ingestão. O pico pela rede foi de ≈277 000 mensagens/s; por loopback a ingestão é menor (≈185 000/s) porque o gerador disputa núcleos com o broker.
  • Leque (roteamento). Em hardware potente o broker entregou ≈1 350 000 mensagens/s aos assinantes (leque ×100) contra ≈22 000/s pela rede.
  • Robustez. Em nenhuma bancada o broker travou ou caiu. Em sobrecarga, mensagens QoS 0 destinadas a assinantes atrasados são descartadas de forma ordenada; o log do broker não contém um único erro em todas as execuções.

Capacidade de conexões simultâneas

Cada conexão é um ciclo completo CONNECT → CONNACK com autenticação; depois a sessão é mantida aberta (verificada com PINGREQ).

Bancada A — pela rede

AlvoEstabelecidasFalhasEstabelecimento p50p99
10100146 ms162 ms
1001000702 ms1,12 s
1000100004,21 s9,78 s
5000500004,64 s8,59 s
10 00010 00004,92 s10,52 s
15 00014 8791217,43 s14,09 s

Bancada B — loopback (subida gradual)

AlvoEstabelecidasFalhasEstabelecimento p50p99
100010000886 ms1,06 s
10 00010 0000903 ms1,55 s
30 00030 0000923 ms1,90 s
50 00041 2190984 ms1,90 s

Análise

  • Pela rede, até 10 000 sem uma única falha; as 121 falhas em 15 000 são esgotamento das portas efêmeras do cliente (16 384). É o limite do gerador, não do broker.
  • Por loopback, depois de ampliar a faixa de portas, o broker sustentou 30 000 sessões sem defeito; em 50 000 restavam vivas cerca de 41 000 ao fim do período de retenção — os dois lados dividem uma máquina. O log do broker permaneceu limpo o tempo todo, sem erros.
  • Achado lateral. Por loopback, uma rajada de conexões brusca demais (1000 dials simultâneos) provoca connection refused: a fila de aceitação transborda, porque sem atraso de rede todos os SYN chegam ao mesmo tempo. Uma subida gradual (200 por vez) elimina o efeito por completo. Em uma rede, a latência suaviza a rajada sozinha.

Vazão de ingestão

Um conjunto de publicadores publica o mais rápido possível; mede-se a taxa de ingestão do broker.

QoS 0 · payload de 64 bytes

PublicadoresBancada A (rede)Bancada B (loopback)
10271 006/s185 012/s
100236 422/s101 457/s
500103 546/s125 324/s

A ingestão é maior pela rede — não porque o broker da bancada A seja mais rápido, mas porque ali o gerador roda em uma máquina separada. Por loopback, cliente e broker dividem os mesmos núcleos, o que limita a taxa conjunta.

QoS 1 (com confirmação PUBACK) · 64 B

PublicadoresBancada A (rede)Bancada B (loopback)
1010 292/s63 606/s
10022 085/s48 983/s

O cliente de teste de QoS 1 é síncrono (espera um PUBACK depois de cada mensagem), então fica preso ao tempo de ida e volta. Por loopback esse tempo é quase nulo, daí o ganho de cerca de 6 vezes. Isso mostra com clareza que os números de QoS 1 são ditados pela latência de rede, não pelo broker.

Varredura de tamanhos de mensagem · QoS 0 · 50 publicadores

TamanhoBancada A (rede)Bancada B (loopback)
64 B277 198/s · 17,7 MB/s101 961/s · 6,5 MB/s
256 B124 997/s · 32,0 MB/s102 029/s · 26,1 MB/s
1024 B38 458/s · 39,4 MB/s102 151/s · 104,6 MB/s

Dois tetos diferentes:

  • Pela rede esbarramos no enlace por volta de 40 MB/s: quando a mensagem cresce, as msg/s caem enquanto os MB/s ficam perto do limite.
  • Por loopback o enlace é enorme, então a contagem de mensagens se mantém (~102 000/s com 50 conexões) e o volume sobe para 104,6 MB/s. Aqui o gargalo é o processamento por mensagem (CPU), não os bytes.

Entrega ponta a ponta

Um carimbo de tempo é embutido no corpo da mensagem; medem-se a entrega real e a latência ponta a ponta. Leque significa entrega a cada assinante cujo filtro corresponda.

Bancada A — pela rede

CenárioPublicaçãoEntregamédia / p50 / p99
10 ass. / 10 pub. / 100 msg/s — normal986/s9863/s1,17 / 1,0 / 3,6 ms
100 ass. / 10 pub. / sem freio261 551/s22 351/s780 / 453 / 678 ms
100 ass. / 10 pub. / 500 msg/s4934/s12 150/s1,87 / 1,77 / 2,83 s
1000 ass. / 5 pub. / 100 msg/s494/s178 961/s2,29 s / 480 / 952 ms

Bancada B — loopback

CenárioPublicaçãoEntregamédia / p50 / p99
10 ass. / 10 pub. / 100 msg/s — normal987/s9867/s73 / ~0 / 555 µs
100 ass. / 10 pub. / sem freio47 557/s1 353 431/s514 / 135 / 251 ms
100 ass. / 10 pub. / 500 msg/s3608/s360 834/s17,1 / 10,5 / 71,6 ms
1000 ass. / 5 pub. / 100 msg/s494/s183 746/s4,73 / 4,54 / 15,1 ms

Análise

  • Latência sob carga normal: 1,17 ms pela rede contra 73 µs por loopback. A diferença é o trajeto de rede.
  • Roteamento sob carga: a máquina potente entregou ≈1,35 milhão de mensagens/s aos assinantes (leque ×100) — duas ordens de grandeza acima da bancada de rede (22 mil/s), onde tanto o broker quanto o enlace são pequenos.
  • Em cenários de leque grande o gerador também vira gargalo (todos os assinantes em um processo e uma máquina), então os picos de entrega são um piso do que o broker consegue fazer.

Frente a frente

IndicadorBancada A — rede (12 núcleos)Bancada B — loopback (28 núcleos)
Conexões sem falhas10 00030 000
Pico de conexões14 879 (limite do cliente)~41 000 (limite de uma máquina)
Ingestão QoS 0 (64 B), pico271 006/s185 012/s
Ingestão QoS 1 (64 B), pico22 085/s63 606/s
Teto de volume≈40 MB/s (enlace)≈105 MB/s (CPU)
Latência (normal), mediana1,0 ms~0 (73 µs em média)
Entrega com leque, pico22 351/s1 353 431/s
Erros no log do brokernenhumnenhum

Ressalvas metodológicas

  • A taxa de ingestão não é diretamente comparável entre as bancadas: na bancada B gerador e broker dividem núcleos; na bancada A o gerador é uma máquina separada.
  • Em cada bancada a carga vem de uma única máquina cliente; em alguns cenários (leque grande, dezenas de milhares de conexões) o gargalo é essa máquina e não o broker.
  • O cliente de teste de QoS 1 é síncrono — os números de QoS 1 subestimam o potencial do broker.
  • As métricas de sistema do broker (CPU e memória durante as execuções) não foram coletadas; o estado do servidor é inferido do log dele (sem erros) e do comportamento do lado cliente.

Reproduzir

Cada execução parte de um único binário loadtest; abaixo estão os comandos dos três modos.

go build -o loadtest ./cmd/loadtest

# Capacidade de conexões (subida gradual contra a fila de aceitação)
./loadtest -addr HOST:1883 -user myelx -pass *** \
    -mode conn -levels 1000,10000,30000,50000 -hold 3s -dial-concurrency 200

# Vazão de ingestão
./loadtest -addr HOST:1883 -user myelx -pass *** \
    -mode pub -pubs 10 -qos 0 -payload 64 -duration 10s

# Entrega ponta a ponta e latência
./loadtest -addr HOST:1883 -user myelx -pass *** \
    -mode pubsub -subs 10 -pubs 10 -qos 0 -rate 100 -payload 64 -duration 10s