Skip to main content

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 prefetch for 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çãoMelhor modoJustificativa
Processamento contínuo de eventosPushMaximiza throughput e usa prefetch para controle de fluxo.
Processamento sob demanda (batch, API)PullEvita manter conexão ativa e dá controle sobre quando consumir.
Aplicações com risco de sobrecargaPullO consumidor dita o ritmo.
Escalabilidade horizontal com múltiplos workersPushRabbitMQ 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á prefetch porque o consumidor controla totalmente o ritmo de leitura.

⚖️ Comparativo final

CaracterísticaPushPull
EntregaAutomática (broker envia)Sob demanda (consumidor busca)
Controle de fluxoprefetch countLógica do consumidor
PerformanceAlta (assíncrono)Menor (síncrono)
Ideal paraStreams contínuos, workersJobs pontuais, APIs, testes
API usadaBasicConsumeBasicGet