Filas com RabbitMQ
O motor RabbitMQ® de Filas oferece mensageria completa para microsserviços: exchanges, routing keys, confirmações e dead-letter. A versão é a 4.4 e o protocolo é AMQP 0-9-1. Para tarefas simples em segundo plano, o motor Valkey pode ser suficiente; veja a comparação em Filas: escolha o motor.
Planos e alta disponibilidade
O RabbitMQ usa os mesmos planos pagos e os mesmos preços das demais Filas: queue-starter, queue-basic, queue-premium e queue-enterprise. Não há plano gratuito para RabbitMQ; o queue-free é só do Valkey. Consulte capacidade e preço no guia de planos.
| Plano | Nós | Tipo de fila padrão | Métricas |
|---|---|---|---|
queue-starter | 1 | clássica | não |
queue-basic | 3, com alta disponibilidade | quorum | não |
queue-premium | 3, com alta disponibilidade | quorum | sim |
queue-enterprise | 3, com alta disponibilidade | quorum | sim |
As filas quorum replicam cada mensagem entre os nós e continuam disponíveis se um nó falhar. Nos planos com 1 nó não há réplica: se o nó ficar indisponível, a fila espera ele voltar. Entre os planos Basic, Premium e Enterprise, troque o plano no card Plano da edição do projeto (permissão Permitir mudança de plano): os 3 nós reiniciam um de cada vez, as conexões abertas caem e a aplicação precisa reconectar, e as filas e mensagens guardadas são mantidas. O Enterprise exige pelo menos 20 GB de armazenamento; amplie o armazenamento antes de trocar para ele. O Starter tem 1 nó e não troca de plano; para sair dele, crie uma fila nova no plano desejado. Para ganhar espaço, aumente o armazenamento. Veja Armazenamento e a API de armazenamento.
Conexão
A conexão usa TLS e tem este formato:
amqps://app:<senha>@rabbitmq-<id>.managed.zenifra.com:<porta>/- Usuário:
app. Virtual host:/. - A senha é exibida apenas na criação e depois de uma rotação de credencial. Depois disso, o Console mostra a URL com a senha mascarada.
- Fora da Zenifra, somente conexões TLS (
amqps) são aceitas. - Guarde a URL como variável de ambiente protegida (por exemplo,
RABBITMQ_URL) no projeto da aplicação.
Por padrão, o host e a porta são públicos. Você pode desligar o acesso público; nesse caso, o serviço só é alcançado pelas conexões privadas entre aplicações. A resposta de GET /v1/managed-services/:id/connection informa o estado em exposure.
Conexão privada
Aplicações da sua organização ligadas ao RabbitMQ por uma conexão privada usam o endereço interno <projeto>.<id-da-organização>.zenifra.local, na porta 5672 com amqp://; o tráfego fica dentro da rede privada. O passo a passo está em Conexão privada com o RabbitMQ.
Node.js e TypeScript
npm install amqplibimport amqp from 'amqplib'
const connection = await amqp.connect(process.env.RABBITMQ_URL!)
const channel = await connection.createConfirmChannel()
// Exchange de dead-letter e a fila que guarda as mensagens rejeitadas
await channel.assertExchange('orders.dlx', 'direct', { durable: true })
await channel.assertQueue('orders.dead', { durable: true })
await channel.bindQueue('orders.dead', 'orders.dlx', 'created')
// Exchange principal, fila de trabalho e binding por routing key
await channel.assertExchange('orders', 'topic', { durable: true })
await channel.assertQueue('orders.created', {
durable: true,
arguments: {
'x-dead-letter-exchange': 'orders.dlx',
'x-dead-letter-routing-key': 'created',
},
})
await channel.bindQueue('orders.created', 'orders', 'orders.created')
// Publicação persistente, com confirmação do servidor
channel.publish('orders', 'orders.created', Buffer.from(JSON.stringify({ id: 42 })), {
persistent: true,
contentType: 'application/json',
})
await channel.waitForConfirms()
// Consumo com confirmação manual
await channel.prefetch(10)
await channel.consume('orders.created', async (message) => {
if (!message) return
try {
console.log('process message', JSON.parse(message.content.toString()))
channel.ack(message)
} catch {
channel.nack(message, false, false) // sem reenfileirar: vai para a dead-letter
}
})O amqplib valida o certificado do servidor quando a URL usa amqps://. O processamento deve ser idempotente: uma mensagem pode ser entregue mais de uma vez depois de uma falha ou de uma reconexão.
Python
python -m pip install pikaimport json
import os
import ssl
from urllib.parse import urlparse
import pika
url = os.environ["RABBITMQ_URL"]
params = pika.URLParameters(url)
params.ssl_options = pika.SSLOptions(ssl.create_default_context(), urlparse(url).hostname)
connection = pika.BlockingConnection(params)
channel = connection.channel()
channel.confirm_delivery()
# Dead-letter
channel.exchange_declare("orders.dlx", exchange_type="direct", durable=True)
channel.queue_declare("orders.dead", durable=True)
channel.queue_bind("orders.dead", "orders.dlx", routing_key="created")
# Exchange principal, fila de trabalho e binding por routing key
channel.exchange_declare("orders", exchange_type="topic", durable=True)
channel.queue_declare(
"orders.created",
durable=True,
arguments={"x-dead-letter-exchange": "orders.dlx", "x-dead-letter-routing-key": "created"},
)
channel.queue_bind("orders.created", "orders", routing_key="orders.created")
# Publicação persistente (a confirmação do servidor é aguardada)
channel.basic_publish(
"orders",
"orders.created",
json.dumps({"id": 42}),
properties=pika.BasicProperties(delivery_mode=2, content_type="application/json"),
)
# Consumo com confirmação manual
def handle(ch, method, properties, body):
try:
print("process message", json.loads(body))
ch.basic_ack(method.delivery_tag)
except Exception:
ch.basic_nack(method.delivery_tag, requeue=False) # vai para a dead-letter
channel.basic_qos(prefetch_count=10)
channel.basic_consume("orders.created", on_message_callback=handle)
channel.start_consuming()Exchanges, routing keys e dead-letter
- Exchange: recebe a mensagem do produtor e a roteia para as filas ligadas a ela. Os tipos mais usados são
direct(routing key exata),topic(padrões comoorders.*) efanout(todas as filas). - Routing key: etiqueta que o produtor coloca na mensagem e que o binding usa para decidir a fila de destino.
- Confirmações: o consumidor confirma com
ackdepois de processar; comnacksem reenfileirar, a mensagem segue para a dead-letter. A confirmação de publicação (waitForConfirms,confirm_delivery) garante que o servidor recebeu a mensagem. - Dead-letter: declare a fila com
x-dead-letter-exchange(e, se quiser,x-dead-letter-routing-key). As mensagens rejeitadas comnacksem reenfileirar ou expiradas vão para a exchange indicada.
Você configura tudo pelo próprio cliente AMQP, no código da aplicação: o usuário app pode criar, alterar e remover exchanges, filas e bindings no virtual host /. Os argumentos mais usados ao declarar uma fila são x-queue-type, x-message-ttl (validade das mensagens), x-max-length e x-max-length-bytes (abaixo do limite do plano), x-dead-letter-exchange e x-single-active-consumer. Não há painel de gerenciamento nem API HTTP do RabbitMQ, e as políticas do servidor são definidas pela Zenifra, como a do tamanho máximo da fila de cada plano.
Ao declarar uma fila sem x-queue-type, ela usa o tipo padrão do plano. Redeclarar uma fila já existente com argumentos diferentes causa erro; crie uma fila nova ou remova a antiga.
Mensagens com entrega agendada
Para entregar uma mensagem só a partir de um horário, publique com o header x-opt-delivery-time: o horário de entrega em milissegundos desde 1970 (Unix epoch), como número inteiro. A fila guarda a mensagem na hora e só a entrega aos consumidores quando o horário chega. Não precisa de plugin nem de exchange especial.
// Entrega daqui a 10 minutos
channel.publish('orders', 'orders.reminder', Buffer.from(JSON.stringify({ id: 42 })), {
persistent: true,
headers: { 'x-opt-delivery-time': Date.now() + 10 * 60 * 1000 },
})import time
channel.basic_publish(
exchange="orders",
routing_key="orders.reminder",
body=json.dumps({"id": 42}),
properties=pika.BasicProperties(
delivery_mode=2,
headers={"x-opt-delivery-time": int(time.time() * 1000) + 10 * 60 * 1000},
),
)- Funciona em filas do tipo
quorum, o padrão nos planos Basic, Premium e Enterprise. No Starter, o padrão é a fila clássica, que ignora o header e entrega na hora; declare a fila comx-queue-type: quorumpara usar a entrega agendada. - As mensagens saem na ordem do horário de entrega, não na ordem de publicação, e contam para o tamanho máximo da fila enquanto esperam.
- Nos nossos testes, nenhuma mensagem saiu antes do horário, e a entrega ocorreu de 5 a 70 ms depois dele. Mensagens agendadas antes de uma troca de plano foram entregues no horário certo depois da troca.
- O plugin antigo
rabbitmq_delayed_message_exchange(headerx-delay) não está disponível; usex-opt-delivery-time.
Limites por plano
| Plano | Conexões | Canais por conexão | Canais no total | Tamanho máximo da mensagem | Tamanho máximo da fila |
|---|---|---|---|---|---|
queue-starter | 100 | 128 | 400 | 4 MiB | 128 MiB |
queue-basic | 300 | 256 | 1.200 | 16 MiB | 256 MiB |
queue-premium | 1.000 | 512 | 3.000 | 16 MiB | 512 MiB |
queue-enterprise | 5.000 | 1.024 | 12.000 | 16 MiB | 2 GiB |
Estes são os limites atuais e podem mudar. "Canais no total" soma os canais de todas as conexões; ao passar dele, o servidor recusa o novo canal. Quando uma fila atinge o tamanho máximo, novas publicações nela são rejeitadas. Quando a memória do serviço enche, as publicações ficam bloqueadas até que os consumidores esvaziem mensagens; mantenha consumidores ativos e acompanhe as métricas.
Desempenho medido
Medimos cada plano em novembro de 2026 com a carga que recomendamos para não perder mensagens: filas duráveis do tipo padrão do plano, mensagens persistentes de 1 KiB, confirmação de publicação e ack manual no consumidor. O cliente usou amqplib (Node.js), conectado pela URL pública com TLS a partir da mesma região, e todas as mensagens confirmadas foram entregues.
Vazão (mensagens publicadas e consumidas por segundo, do começo ao fim do teste):
| Plano | 1 fila, 2 produtores e 2 consumidores | 4 filas, 1 produtor e 1 consumidor em cada |
|---|---|---|
queue-starter | cerca de 3.100 | cerca de 3.100 |
queue-basic | cerca de 6.700 | cerca de 8.800 |
queue-premium | cerca de 8.900 | cerca de 10.000 |
queue-enterprise | cerca de 7.500 | cerca de 9.600 |
Latência (da publicação até a entrega ao consumidor):
| Plano | 100 mensagens/s: mediana | 100 mensagens/s: p99 | 1.000 mensagens/s: mediana | 1.000 mensagens/s: p99 |
|---|---|---|---|---|
queue-starter | 1,5 ms | 4,2 ms | 3,7 ms | 27 ms |
queue-basic | 7,2 ms | 13 ms | 12 ms | 23 ms |
queue-premium | 7,9 ms | 39 ms | 12 ms | 42 ms |
queue-enterprise | 8,2 ms | 17 ms | 12 ms | 32 ms |
Como ler esses números:
- No Starter, a fila clássica de 1 nó responde mais rápido, mas a CPU do plano chega ao limite perto de 3.000 mensagens por segundo. Com o servidor no limite, publicar ganha prioridade e o consumo atrasa; as mensagens ficam na fila e são entregues depois.
- A partir do Basic, cada mensagem é gravada em disco nos 3 nós antes da confirmação. Isso soma alguns milissegundos à latência e põe uma única fila perto de 7.000 a 9.000 mensagens por segundo, qualquer que seja o plano. Distribuir a carga entre várias filas aumenta um pouco a vazão total: com 16 filas em paralelo, o Basic ficou em cerca de 8.400 e o Enterprise em cerca de 11.300 mensagens por segundo, com CPU de sobra nos dois.
- Os planos maiores não deixam uma mensagem mais rápida: eles aceitam mais conexões e canais, guardam filas maiores e têm folga de CPU e memória para muitas filas, consumidores e picos.
- Os resultados variam com o tamanho das mensagens, o número de filas e de conexões, o uso de confirmações e a distância entre a aplicação e o serviço. Para decidir, meça a sua própria carga em uma fila de teste por hora e remova-a ao terminar.
Troca de plano com tráfego
Trocamos o plano de Basic para Premium e de Premium para Enterprise com um produtor e um consumidor ligados, publicando 200 mensagens por segundo, e com 1.000 mensagens guardadas em outra fila, sem consumidor:
| Medida | Resultado |
|---|---|
| Duração da troca, com os 3 nós reiniciando um de cada vez | cerca de 4 minutos |
| Mensagens confirmadas que se perderam | nenhuma |
| Quedas de conexão do produtor e do consumidor | 2 de cada, com reconexão em cerca de 1 segundo |
| Maior pausa sem confirmação de publicação | cerca de 1,4 segundo |
| Mensagens entregues duas vezes | cerca de 0,03%, todas reentregues pelo servidor com redelivered marcado, porque o ack do consumidor não chegou antes da queda |
| Mensagens guardadas lidas depois da troca, com a mesma credencial e na mesma fila | 1.000 de 1.000 |
Para atravessar a troca sem perder mensagens, a aplicação precisa reconectar sozinha, reenviar as publicações que não foram confirmadas e tratar mensagens repetidas com uma chave de idempotência.
Métricas
Nos planos Premium e Enterprise, a página do projeto mostra filas, mensagens prontas e sem confirmação, consumidores, taxas de publicação e de entrega e um aviso quando a memória está cheia. Mensagens sem confirmação que crescem indicam consumidores lentos ou sem ack.
Backups
O backup automático está incluído no plano, com restauração pelo suporte. Veja Backups automáticos.
O que o backup garante, até o último backup realizado:
- as mensagens em filas persistentes (duráveis ou quorum);
- a configuração: exchanges, filas, bindings, usuários e políticas.
O que não é garantido:
- mensagens publicadas depois do último backup;
- mensagens em filas não persistentes.
Para não perder mensagens, use filas duráveis, publique com persistent e confirmação de publicação e mantenha consumidores idempotentes.
Perguntas frequentes
Posso conectar sem TLS?
Não. Fora da Zenifra, somente amqps:// é aceito.
Posso instalar plugins ou abrir o painel de gerenciamento?
Não. Os plugins são definidos pela Zenifra e nenhum plugin opcional fica ligado, como shovel, federation, streams, MQTT, STOMP ou a exchange de mensagens atrasadas (delayed message); para atrasar uma entrega, use a entrega agendada. O painel de gerenciamento e a API HTTP do RabbitMQ não ficam expostos; use as métricas da página do projeto. Se a sua aplicação depende de um plugin, fale com o suporte.
Posso usar vários virtual hosts ou usuários?
A conexão fornecida usa o virtual host / e o usuário app.
O RabbitMQ garante entrega exactly-once?
Não. Como em qualquer RabbitMQ, a entrega é at-least-once: se a conexão cai depois que o consumidor recebeu a mensagem e antes de o ack chegar ao servidor, o servidor entrega a mensagem de novo, com redelivered marcado; e um produtor que reenvia uma publicação sem confirmação pode gravá-la duas vezes. Isso acontece em quedas de rede, reinícios e trocas de plano. Use uma chave de idempotência na aplicação para processar cada mensagem uma vez só.
Próximos passos
- Filas: escolha o motor
- Filas com Valkey
- Conexões privadas entre aplicações
- API de serviços gerenciados
RabbitMQ® é uma marca da Broadcom, Inc. nos Estados Unidos e em outros países. A Zenifra não é afiliada à Broadcom nem endossada por ela.
Última atualização em
Filas com Valkey: Streams e Pub/Sub
Filas com motor Valkey: Streams, consumer groups, confirmação, recuperação de pendências, Pub/Sub e exemplos em Node.js e Python.
Armazém: armazenamento de objetos
Guarde imagens, vídeos, backups e outros arquivos no Armazém da Zenifra, com buckets privados, chaves por aplicação e links que expiram.