Testes de brokers

Configurar ambientes MQTT de desenvolvimento, staging e produção

Como separar ambientes MQTT de desenvolvimento, staging e produção: broker por ambiente, prefixos de topic, credenciais e ACLs próprias, promoção e smoke tests.

Atualizado · 8 min de leitura

Configurar ambientes MQTT de desenvolvimento, staging e produção

O jeito mais limpo de rodar MQTT em desenvolvimento, staging e produção é fácil de resumir: dê a cada ambiente o seu próprio broker (ou instância isolada de broker) e as suas próprias credenciais, mantenha os nomes de topic idênticos entre os ambientes e mude apenas a configuração (URL, usuário, senha) quando o código passa de um para o outro. Todo o resto deste guia serve para deixar isso entediante e seguro.

Para que serve cada ambiente

DesenvolvimentoStagingProdução
ObjetivoIteração rápida, experimentosRelease candidate, testes de integração e de cargaDispositivos e clientes reais
BrokerDocker local ou um endpoint de teste compartilhadoMesmo tipo de broker e mesmas configurações da produçãoDedicado, monitorado
DadosFalsos, descartáveisRealistas, gerados ou anonimizadosReais
Quem se conectaDesenvolvedores, simuladoresCI, dispositivos de teste, QAFrota e serviços de backend
CredenciaisPor desenvolvedor ou um usuário de dev compartilhadoPor serviço, só de stagingPor serviço e por dispositivo
TLSOpcionalObrigatório, igual à produçãoObrigatório

Staging só é útil se se comportar como produção. Um broker de staging sem TLS, sem autenticação ou com ACLs escancaradas vai aprovar releases que quebram no primeiro dia em produção.

Três formas de separar os ambientes

ModeloComo funcionaBom paraAtenção
Um broker por ambienteHosts ou instâncias separados; topics idênticosProdução, e qualquer equipe que possa bancarMais endpoints para gerenciar
Broker compartilhado, topics com prefixodev/..., stg/... em um broker, ACLs por ambienteDev e staging com orçamento curtoUma ACL mal configurada vaza dados entre ambientes; capacidade compartilhada
HíbridoProdução isolada; dev e staging dividem um brokerA maioria das equipes pequenas e médiasMantenha as credenciais de produção totalmente fora do broker compartilhado

Seja qual for a escolha, produção nunca divide broker com testes. Um teste de carga, um simulador descontrolado ou uma mensagem retida publicada por engano não podem chegar a dispositivos reais.

Prefixos de topic do jeito certo

Com um broker por ambiente, não coloque o ambiente no topic. factory/line1/temp é o mesmo topic em staging e em produção, então assinaturas, dashboards, regras e arquivos de ACL podem ser promovidos sem edição.

Quando os ambientes dividem um broker, o prefixo é obrigatório, e precisa ser adicionado em um único lugar. O pior padrão são verificações de ambiente espalhadas pelo código (if env == "prod": topic = ...). Monte cada topic com um helper que adiciona o prefixo configurado, e deixe o prefixo vazio quando o ambiente tiver broker próprio:

mqtt-config.mjs
import mqtt from "mqtt";

export const ENV = process.env.APP_ENV ?? "dev";
const url = process.env.MQTT_URL;
const prefix = process.env.MQTT_TOPIC_PREFIX ?? "";   // "" quando o ambiente tem broker próprio

if (!url) throw new Error("MQTT_URL is not set");

export const topic = (t) => (prefix ? `${prefix}/${t}` : t);

export function connect(name) {
  return mqtt.connect(url, {
    clientId: `${name}-${ENV}-${Math.random().toString(16).slice(2, 8)}`,
    username: process.env.MQTT_USER,
    password: process.env.MQTT_PASS,
    protocolVersion: 5,
    reconnectPeriod: 2000,
  });
}
uso
import { connect, topic } from "./mqtt-config.mjs";

const client = connect("ingest");
client.on("connect", () => client.subscribe(topic("factory/+/temp"), { qos: 1 }));

Incluir o ambiente no client ID também deixa os logs do broker legíveis: você vê na hora que ingest-stg-3fa9c1 é um serviço de staging. Em um broker de dev compartilhado, dê a cada desenvolvedor um prefixo pessoal como testmqtt/dev-alice para que os experimentos nunca colidam; os detalhes estão em como nomear topics de teste para que nunca colidam.

Credenciais e ACLs por ambiente

Cada ambiente tem os seus próprios usuários, e uma credencial de um ambiente precisa ser inútil em outro. Nomeie os usuários por serviço e ambiente (ingest-stg, ingest-prod) para que uma credencial vazada ou mal usada salte aos olhos nos logs.

Em um broker compartilhado de dev e staging, são as ACLs que realmente separam os ambientes. Um arquivo de ACL do Mosquitto para esse caso:

acl (broker compartilhado de dev + staging)
user ingest-dev
topic read dev/telemetry/#
topic write dev/cmd/#

user ingest-stg
topic read stg/telemetry/#
topic write stg/cmd/#

Verifique a separação em vez de confiar nela: conecte-se com o usuário de dev e tente assinar stg/#. Com MQTT 5 o broker devolve um código de falha no SUBACK (0x87 Not authorized); com MQTT 3.1.1 você recebe 0x80 ou simplesmente nenhuma mensagem. Testar permissões de ACL MQTT mostra como automatizar esses testes negativos.

Configuração por ambiente

Mantenha um arquivo de configuração por ambiente e carregue-o na inicialização; o código continua o mesmo.

.env.dev
APP_ENV=dev
MQTT_URL=mqtt://broker.connectmq.com:1883
MQTT_USER=username
MQTT_PASS=password
MQTT_TOPIC_PREFIX=testmqtt/dev-alice
.env.staging
APP_ENV=staging
MQTT_URL=mqtts://<your-staging-host>:8883
MQTT_USER=ingest-stg
MQTT_PASS=<do seu cofre de segredos>
MQTT_TOPIC_PREFIX=

Os valores de produção ficam apenas no cofre de segredos do deploy de produção, nunca no repositório e nunca em jobs de teste do CI. Adicione uma proteção ao setup dos testes para que um engano não aponte a suíte para produção:

test/setup.mjs
import { ENV } from "../mqtt-config.mjs";

if (ENV === "prod" || ENV === "production") {
  throw new Error("Refusing to run tests against production");
}

Os dispositivos precisam da mesma disciplina. O firmware não deve ter o broker fixo no código; o ambiente é definido no provisionamento junto com as credenciais do dispositivo, para que um dispositivo de staging não vá parar na frota de produção. Veja provisionamento de dispositivos MQTT.

Promovendo a configuração do broker

A configuração do broker (listeners, TLS, limites, arquivos de ACL) deve passar pelos ambientes da mesma forma que o código:

  1. Guarde a configuração do broker no git como um template mais valores por ambiente (hostnames, caminhos de certificados, limites). O gerador de configuração do Mosquitto é um jeito rápido de criar um arquivo inicial correto.
  2. Revise mudanças de ACL como código: um único # na linha errada libera tudo.
  3. Aplique a mudança em dev, depois em staging, rode os testes e só então promova o mesmo commit para produção.
  4. Compare staging com produção antes de cada release. Qualquer diferença que não seja um hostname, um segredo ou um limite de capacidade é um bug esperando para acontecer.

Smoke test em cada ambiente

Depois de cada deploy, rode uma ida e volta completa com as credenciais daquele ambiente. O mesmo script funciona em todos:

smoke.sh
#!/usr/bin/env bash
set -euo pipefail
: "${MQTT_HOST:?}" "${MQTT_USER:?}" "${MQTT_PASS:?}"
T="${MQTT_TOPIC_PREFIX:-testmqtt}/smoke/$(date +%s)"
OUT=$(mktemp)
mosquitto_sub -h "$MQTT_HOST" -p 8883 --capath /etc/ssl/certs \
  -u "$MQTT_USER" -P "$MQTT_PASS" -t "$T" -C 1 -W 10 > "$OUT" &
sleep 1
mosquitto_pub -h "$MQTT_HOST" -p 8883 --capath /etc/ssl/certs \
  -u "$MQTT_USER" -P "$MQTT_PASS" -t "$T" -m ok -q 1
wait
grep -qx ok "$OUT" && echo "smoke test passed on $MQTT_HOST"

-W 10 faz o subscriber sair com erro se nada chegar em dez segundos, então um ambiente quebrado derruba o pipeline em vez de travá-lo. Para uma versão mais completa, veja um script de smoke test MQTT; para uma verificação manual, conecte-se com o cliente MQTT online usando as credenciais do ambiente.

Erros comuns

  • As mesmas credenciais em todo lugar. Uma senha de dev vazada vira incidente de produção.
  • Staging sem TLS ou autenticação. Bugs de certificado e de permissão aparecem pela primeira vez em produção.
  • Verificações de ambiente na lógica de negócio. Promova configuração, não ramificações de código.
  • Dados de teste retidos em um broker compartilhado. Limpe-os depois dos testes, ou as próximas execuções vão ler um estado velho.
  • Dispositivos de staging esquecidos. Hardware de teste apontando para produção por causa de uma configuração antiga polui os dados reais.

Antes de entrar no ar, percorra o checklist de produção MQTT no próprio ambiente de produção, não no staging.

Brokers separados, credenciais separadas, topics idênticos e um único lugar onde a configuração muda: com essas quatro regras, levar uma release de dev para staging e para produção é uma troca de configuração e um smoke test, não uma migração.

Perguntas frequentes

Desenvolvimento, staging e produção devem compartilhar um broker MQTT?

Produção deve ter o seu próprio broker ou instância isolada. Desenvolvimento e staging podem dividir um broker se cada ambiente tiver credenciais próprias, prefixo de topic próprio e ACLs que os mantenham separados, mas instâncias separadas são mais simples de entender.

O nome do ambiente deve fazer parte do topic MQTT?

Só quando os ambientes compartilham um broker. Com um broker por ambiente, mantenha os topics idênticos em todos eles para promover código e dashboards sem alterações. Se precisar de prefixo, adicione-o em um único lugar do código do cliente.

Como impedir que os testes publiquem em produção?

Dê as credenciais de produção apenas aos serviços de produção, mantenha-as fora dos jobs de teste do CI e adicione uma proteção no setup dos testes que se recusa a rodar quando o ambiente ou a URL do broker configurados são de produção.