Testes de brokers

Teste de carga MQTT com JMeter: plugin, thread groups e resultados

Teste de carga em broker MQTT com Apache JMeter: instale o plugin MQTT, monte thread groups de publishers e subscribers, rode sem GUI e leia os resultados.

Atualizado · 9 min de leitura

Teste de carga MQTT com JMeter: plugin, thread groups e resultados

O Apache JMeter consegue fazer teste de carga em um broker MQTT assim que você adiciona um plugin MQTT: cada thread do JMeter vira um cliente MQTT que conecta, publica ou se inscreve, e os timers, listeners e o relatório HTML do JMeter fazem o resto. Se o seu time já usa JMeter para HTTP, você mantém uma única ferramenta, um único formato de relatório e um único job de CI também para os testes MQTT.

Este guia instala o plugin, monta um test plan com publishers e subscribers, executa sem GUI e explica o que os números realmente medem.

Escolhendo um plugin MQTT

O JMeter não tem sampler MQTT embutido. A opção mais usada é o emqx/mqtt-jmeter (publicado originalmente pela XMeter). Ele adiciona quatro samplers:

SamplerO que faz
MQTT ConnectAbre uma conexão (TCP, SSL, WS ou WSS) e a mantém para a thread
MQTT Pub SamplerPublica em um topic com o QoS, a flag retain e o payload escolhidos
MQTT Sub SamplerFaz subscribe e amostra as mensagens recebidas por uma janela de tempo ou uma contagem de mensagens
MQTT DisConnectFecha a conexão da thread

Os samplers Pub e Sub reutilizam a conexão criada pelo sampler Connect na mesma thread. Se ainda não existe conexão, eles falham imediatamente — exatamente o que você quer ver no relatório.

Instalar o JMeter e o plugin

O JMeter precisa de um runtime Java (Java 8 ou mais recente para o JMeter 5.6). Baixe o JMeter e copie o jar do plugin da página de releases do projeto para lib/ext:

Instalar o JMeter 5.6.3 e o plugin MQTT
curl -LO https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.6.3.tgz
tar xzf apache-jmeter-5.6.3.tgz

# baixe o jar mais recente em https://github.com/emqx/mqtt-jmeter/releases
cp ~/Downloads/mqtt-xmeter-*.jar apache-jmeter-5.6.3/lib/ext/

apache-jmeter-5.6.3/bin/jmeter   # abre a GUI para montar o plan

Depois de reiniciar, clique com o botão direito em um Thread Group → Add → Sampler e os quatro samplers MQTT aparecem. Use a GUI apenas para montar e depurar o plan; gere a carga real pela linha de comando.

Antes de qualquer carga, confirme que host, porta e credenciais funcionam com um único cliente no cliente MQTT online. Uma senha errada com 500 threads gera 500 erros idênticos e nenhuma informação útil. Os exemplos usam broker.connectmq.com, um endpoint compartilhado pensado para verificações funcionais rápidas; para a execução de carga em si, aponte -Jhost e as credenciais para a sua própria instância privada de broker.

Montar o test plan

Um teste de telemetria realista tem dois grupos de clientes: publishers que enviam dados dos dispositivos e subscribers que os consomem. Esta estrutura dá a cada publisher seu próprio topic e seu próprio subscriber (um para um), então você mede o roteamento, não o fan-out:

mqtt-load.jmx — árvore do test plan
Test Plan
├── User Defined Variables: HOST, PORT, THREADS, RATE
├── Thread Group "subscribers"   threads=${THREADS}  ramp-up=30 s
│   ├── MQTT Connect           clientId prefix "jm_sub_" + random suffix
│   └── MQTT Sub Sampler       topic testmqtt/jmeter/${__threadNum}/data
├── Thread Group "publishers"    threads=${THREADS}  ramp-up=60 s  duration=600 s
│   ├── Once Only Controller
│   │   └── MQTT Connect       clientId prefix "jm_pub_" + random suffix
│   └── MQTT Pub Sampler       topic testmqtt/jmeter/${__threadNum}/data
│       └── Constant Throughput Timer   ${RATE} samples/min, all active threads
├── tearDown Thread Group → MQTT DisConnect
└── Summary Report (GUI debugging only)

Configurações principais, sampler por sampler:

  • Variáveis. Defina HOST como ${__P(host,broker.connectmq.com)}, PORT como ${__P(port,1883)} e assim por diante. __P lê uma propriedade passada com -J na linha de comando e usa o valor padrão quando ela não existe, então um único .jmx serve para todos os ambientes.
  • MQTT Connect. Servidor ${HOST} (sem prefixo tcp://), porta ${PORT}, protocolo TCP (ou SSL na porta 8883, WSS na 8084), usuário e senha vindos de propriedades e keep alive igual ao dos seus dispositivos. Ative o sufixo aleatório do client ID — duas threads com o mesmo client ID derrubariam uma à outra do broker.
  • Once Only Controller. A thread publisher conecta só na primeira iteração e depois repete o Pub sampler. Sem ele, cada iteração abriria uma nova conexão e você estaria testando taxa de conexão em vez de throughput.
  • MQTT Pub Sampler. QoS 1, retain desligado, tipo de payload "random string with fixed length" do tamanho das suas mensagens reais (por exemplo 256 bytes) e "Add timestamp in payload" ativado para que os subscribers calculem a latência.
  • MQTT Sub Sampler. Mesmo QoS, "Payload includes timestamp" ativado e amostragem por "number of received messages" (por exemplo 100). Cada amostra passa a representar um lote de mensagens e informa a latência delas.
  • Constant Throughput Timer. A meta é em amostras por minuto. Para 1.000 mensagens por segundo somando todos os publishers, configure 60.000 e escolha "all active threads in current thread group". Coloque-o como filho do Pub sampler para que ele controle apenas o ritmo de publicação.

${__threadNum} é o número da thread dentro do próprio grupo, então o publisher 17 e o subscriber 17 compartilham testmqtt/jmeter/17/data. Confira o padrão com o topic matcher se mudar para subscriptions com wildcards.

Rodar sem GUI e gerar o relatório

O modo GUI distorce os resultados: renderizar listeners consome CPU do gerador de carga. Rode em modo não GUI, grave as amostras em um arquivo .jtl e deixe o JMeter gerar o dashboard HTML no final:

Executar o plan pela linha de comando
export MQTT_USER=username MQTT_PASS=password
HEAP="-Xms1g -Xmx4g" apache-jmeter-5.6.3/bin/jmeter -n \
  -t mqtt-load.jmx \
  -Jhost=broker.connectmq.com -Jport=1883 \
  -Juser="$MQTT_USER" -Jpass="$MQTT_PASS" \
  -Jthreads=200 -Jrate=60000 \
  -l results.jtl -e -o report/

-n é o modo não GUI, -l o arquivo de resultados e -e -o gera o dashboard em uma pasta vazia. A variável HEAP é lida pelo script de inicialização jmeter; aumente-a quando subir o número de threads, porque cada thread mantém um cliente MQTT completo.

Listeners: o que manter e o que desativar

ListenerUse paraDurante a carga?
View Results TreeDepurar uma thread, conferir payloadsNão — desative
Summary Report / Aggregate ReportContagens rápidas por sampler, % de erro, throughputSó em ensaios na GUI
Arquivo .jtl + dashboard HTML (-e -o)Relatório final: percentis, throughput ao longo do tempoSim
Backend Listener (InfluxDB)Gráficos ao vivo no Grafana em execuções longasSim, se precisar de dados ao vivo

O dashboard HTML agrupa os resultados pelo label do sampler, então dê nomes claros ("Pub QoS1 256B", "Sub batch 100") — os labels são os títulos do seu relatório.

O que os números significam

O JMeter mostra um "response time" para cada amostra, mas cada sampler MQTT mede uma coisa diferente:

SamplerO tempo decorrido significaFique de olho em
MQTT ConnectDo CONNECT até o CONNACK (incluindo o handshake TLS)Erros e conexões lentas durante o ramp-up
MQTT Pub SamplerTempo para entregar a mensagem; com QoS 1/2 inclui a espera pelo acknowledgement do brokerTempo subindo = back-pressure do broker ou da rede
MQTT Sub SamplerA janela de amostragem configurada, não a latência de entregaMensagens recebidas por amostra e latência calculada pelos timestamps

Os dois números mais importantes são o throughput de publicação (amostras Pub por segundo, no dashboard) e a latência ponta a ponta (do cálculo de timestamps do Sub sampler). Se as mensagens recebidas ficam atrás das enviadas, algo está sendo descartado ou enfileirado; repita com QoS 1 para separar problemas de capacidade de perdas do QoS 0. Uma análise mais profunda de percentis e falsos gargalos está em interpretando resultados de benchmark MQTT.

Erros de conexão que aparecem exatamente em um número redondo de threads geralmente indicam um limite do sistema operacional no gerador de carga ou um limite de conexões no broker — veja too many connections e consulte o reason code na ferramenta de reason codes MQTT.

Escalando o gerador de carga

Cada thread do JMeter é uma thread Java com seu próprio cliente MQTT, então o JMeter é mais pesado por conexão do que ferramentas baseadas em Erlang ou Go. Limites práticos:

  • Aumente o ulimit -n no gerador de carga e dê heap suficiente ao JMeter.
  • Acompanhe a CPU do gerador. Acima de uns 80 %, suas medições descrevem o JMeter, não o broker.
  • Para mais conexões, use o modo distribuído do JMeter (-R host1,host2) para que várias máquinas rodem o mesmo plan, ou leve o teste puro de conexões para o emqtt-bench e deixe o JMeter para testes de cenário.
  • As versões 2.x do plugin trazem samplers de connect/disconnect em lote que abrem várias conexões por thread; confira as release notes se precisar reduzir o número de threads.

Um fluxo repetível com JMeter

  1. Verifique uma conexão manualmente no cliente online.
  2. Rode o plan na GUI com 2 threads e o View Results Tree ativado; confirme que todos os samplers passam.
  3. Desative o View Results Tree, salve e rode sem GUI a 10 %, 50 %, 100 % e 150 % do pico esperado.
  4. Guarde os .jtl e dashboards de cada execução junto com as métricas de CPU, memória e conexões do broker.
  5. Faça commit do .jmx no seu repositório e rode de novo após cada atualização do broker.

Acompanhe ao vivo o tráfego do teste JMeter

O JMeter não é o gerador de carga MQTT mais leve, mas é prático quando o seu time já o conhece: plans parametrizados, timers para taxas exatas de mensagens e um relatório HTML pronto. Mantenha os samplers simples, rode sem GUI e leia o tempo de cada sampler pelo que ele realmente mede.

Perguntas frequentes

O JMeter suporta MQTT nativamente?

Não. O JMeter não tem um sampler MQTT embutido. Você adiciona um plugin como o emqx/mqtt-jmeter (antigo XMeter), que traz os samplers Connect, Pub, Sub e DisConnect. Copie o jar para lib/ext e reinicie o JMeter.

O JMeter consegue testar MQTT 5?

O plugin emqx/mqtt-jmeter documenta MQTT 3.1 e 3.1.1. Se o seu teste depende de recursos do MQTT 5 como reason codes, user properties ou session expiry, use uma ferramenta com suporte a MQTT 5, como emqtt-bench ou k6 com xk6-mqtt.

Quantas conexões MQTT uma máquina com JMeter consegue abrir?

Depende do heap, da CPU e dos limites do sistema operacional, porque cada thread do JMeter mantém uma conexão MQTT. Aumente o heap e o ulimit -n, rode sem GUI e use o modo distribuído ou uma ferramenta mais leve como emqtt-bench quando precisar de dezenas de milhares de conexões.