Fanout, Consumidores Offline e DLQ no RabbitMQ | RabbitMQ
- Fanout, Consumidores Offline e DLQ no RabbitMQ | RabbitMQ
Conceitos fundamentais
O padrão fanout funciona como broadcast:
- O producer publica em um exchange
- O exchange replica a mensagem para todas as filas vinculadas
- Cada fila possui seu próprio consumidor
- Não existe dependência entre consumidores
Esse padrão segue o modelo de multiple-receiver (publish-subscribe)
Comportamento com consumidores offline
Cenário
- 1 exchange fanout
- 5 filas (1 por consumidor)
- 1 consumidor offline
Resultado
- A mensagem é entregue para todas as filas
- O consumidor offline:
- não processa
- não confirma (ACK)
- a mensagem permanece na fila
Observação importante
- A mensagem não é perdida, desde que:
- fila seja durável (
durable = true) - mensagem seja persistente (
delivery_mode = 2)
- fila seja durável (
Confirmação de mensagem (ACK)
Existem dois níveis distintos:
Confirmação do producer (Publisher Confirm)
- O broker confirma que recebeu a mensagem
- Independe dos consumidores
- Acontece normalmente mesmo com consumidores offline
Confirmação do consumidor (ACK)
- Cada consumidor confirma individualmente
- Se estiver offline:
- não há ACK
- mensagem fica pendente
Dead Letter Queue (DLQ)
A DLQ (Dead Letter Queue) é uma fila de fallback para mensagens que falharam.
Importante
- DLQ não é usada para consumidores offline
- DLQ é usada para falhas de processamento
Quando a DLQ é acionada
A mensagem vai para DLQ quando ocorre:
basic.nackcomrequeue = falsebasic.rejectcomrequeue = false- Expiração por TTL
- Fila atinge limite (
max-length) - Outras regras de dead-letter configuradas
Fluxo completo
Producer
↓
Exchange (fanout)
↓
Fila A → Consumer OK → ACK
Fila B → Consumer OFF → mensagem fica na fila
Fila C → Consumer ERRO → NACK (requeue=false) → DLQ
Exemplo em C# (NACK para DLQ)
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
// rejeita mensagem e envia para DLQ
channel.BasicNack(deliveryTag: ea.DeliveryTag, multiple: false, requeue: false);
Configuração de DLQ
Criação da fila principal com DLQ
var args = new Dictionary<string, object>
{
{ "x-dead-letter-exchange", "dlx-exchange" }
};
channel.QueueDeclare(
queue: "fila-principal",
durable: true,
exclusive: false,
autoDelete: false,
arguments: args
);
Criação da DLQ
channel.ExchangeDeclare("dlx-exchange", ExchangeType.Direct);
channel.QueueDeclare(
queue: "fila-dlq",
durable: true,
exclusive: false,
autoDelete: false
);
channel.QueueBind(
queue: "fila-dlq",
exchange: "dlx-exchange",
routingKey: ""
);
Diferença conceitual
| Situação | Comportamento |
|---|---|
| Consumidor offline | Mensagem fica na fila |
| Erro no processamento | Pode ir para DLQ |
| TTL expirado | Vai para DLQ |
| Fila cheia | Vai para DLQ |
Insight arquitetural
- Fanout desacopla consumidores completamente
- Cada fila representa um “destino independente”
- DLQ trata mensagens problemáticas, não indisponibilidade
Esse modelo é típico de arquiteturas orientadas a eventos, onde componentes reagem de forma independente
Padrão recomendado em produção
- Retry com requeue controlado
- Retry com delay (ex: exchange de retry)
- DLQ como fallback final
- Monitoramento de filas (backlog)