Pull e Push RabbitMQ | CSharp
- Pull e Push RabbitMQ | CSharp
📨 1. Modo Push (Padrão)
Como funciona
-
O broker (RabbitMQ) envia automaticamente as mensagens para o consumidor assim que elas chegam na fila.
-
Isso ocorre de forma assíncrona, ou seja, o consumidor não precisa pedir explicitamente cada mensagem.
-
O fluxo é controlado por dois mecanismos principais:
prefetch count: número máximo de mensagens que o consumidor pode receber sem confirmar (ack) as anteriores.- Confirmações (ACKs): o consumidor confirma ao broker quando terminou de processar uma mensagem.
Vantagens
- Alta performance: mensagens fluem continuamente, sem a latência de “pedidos” explícitos.
- Ideal para workloads contínuos, como filas com tráfego constante e consumidores ativos o tempo todo.
- Escalabilidade natural: o broker pode balancear automaticamente as mensagens entre múltiplos consumidores da mesma fila.
Desvantagens
- Pode haver acúmulo de mensagens em memória do consumidor se o
prefetchfor alto e o consumidor for lento. - Difícil controle fino do ritmo de consumo, já que o broker decide quando enviar.
- Se o consumidor cair antes de enviar ACK, as mensagens não confirmadas voltam à fila (requeue), o que pode causar redelivery e duplicação de processamento.
🔄 2. Modo Pull
Como funciona
- O consumidor solicita manualmente as mensagens, usando chamadas como
basic.get. - O broker responde somente quando há mensagens disponíveis.
- O consumidor decide quando e quantas mensagens buscar, sem necessidade de
prefetch.
Vantagens
- Controle total sobre o ritmo de consumo — útil para aplicações que processam sob demanda.
- Mais simples para casos ocasionais ou debugging, pois você pode buscar uma mensagem por vez.
- Pode reduzir o risco de sobrecarga no consumidor.
Desvantagens
- Menor desempenho: cada chamada gera uma requisição/resposta HTTP/TCP, aumentando a latência.
- Menos eficiente para processamento contínuo, pois não há fluxo constante.
- Menor paralelismo, já que cada “pull” é uma operação síncrona.
⚖️ Quando usar cada modo
| Situação | Melhor modo | Justificativa |
|---|---|---|
| Processamento contínuo de eventos | Push | Maximiza throughput e usa prefetch para controle de fluxo. |
| Processamento sob demanda (batch, API) | Pull | Evita manter conexão ativa e dá controle sobre quando consumir. |
| Aplicações com risco de sobrecarga | Pull | O consumidor dita o ritmo. |
| Escalabilidade horizontal com múltiplos workers | Push | RabbitMQ faz o balanceamento automático entre consumidores. |
🧩 Exemplo em .NET
Instale o pacote NuGet:
dotnet add package RabbitMQ.Client
E crie a conexão e o canal (o código base é o mesmo para os dois modos):
using RabbitMQ.Client;
using System;
using System.Text;
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
// Declara uma fila (caso ainda não exista)
channel.QueueDeclare(queue: "minha_fila",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
🟢 1. Modo Push (padrão) — usando EventingBasicConsumer
No modo Push, o broker envia automaticamente as mensagens ao consumidor assim que estão disponíveis.
using RabbitMQ.Client.Events;
// Define o prefetch (controle de fluxo)
channel.BasicQos(prefetchSize: 0, prefetchCount: 5, global: false);
var consumer = new EventingBasicConsumer(channel);
// Evento chamado toda vez que uma mensagem é entregue
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
Console.WriteLine($"[x] Recebida: {message}");
// Simula processamento
System.Threading.Thread.Sleep(1000);
// Confirma o processamento
channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
};
// Inicia o consumo
channel.BasicConsume(queue: "minha_fila",
autoAck: false, // false → controle manual de ack
consumer: consumer);
Console.WriteLine("Consumidor (PUSH) iniciado. Pressione [enter] para sair.");
Console.ReadLine();
🔍 Explicando:
BasicQos→ define o prefetch count, limitando quantas mensagens o consumidor pode ter “em trânsito”.BasicConsume→ registra o consumidor para receber mensagens automaticamente.autoAck: false→ requer confirmação manual (BasicAck), o que evita perda de mensagens.
🟠 2. Modo Pull — usando BasicGet
No modo Pull, o consumidor pede explicitamente a próxima mensagem. Útil quando você quer processar sob demanda ou em intervalos definidos.
while (true)
{
var result = channel.BasicGet(queue: "minha_fila", autoAck: false);
if (result != null)
{
var message = Encoding.UTF8.GetString(result.Body.ToArray());
Console.WriteLine($"[x] Recebida: {message}");
// Simula processamento
System.Threading.Thread.Sleep(1000);
// Confirma manualmente
channel.BasicAck(deliveryTag: result.DeliveryTag, multiple: false);
}
else
{
Console.WriteLine("Nenhuma mensagem disponível no momento...");
System.Threading.Thread.Sleep(2000);
}
}
🔍 Explicando:
BasicGet→ busca sincronamente uma única mensagem da fila.- Se não houver mensagem, retorna
null. - Não há
prefetchporque o consumidor controla totalmente o ritmo de leitura.
⚖️ Comparativo final
| Característica | Push | Pull |
|---|---|---|
| Entrega | Automática (broker envia) | Sob demanda (consumidor busca) |
| Controle de fluxo | prefetch count | Lógica do consumidor |
| Performance | Alta (assíncrono) | Menor (síncrono) |
| Ideal para | Streams contínuos, workers | Jobs pontuais, APIs, testes |
| API usada | BasicConsume | BasicGet |