Skip to main content

Backpressure em Sistemas Distribuídos | Arquitetura

  • Backpressure em Sistemas Distribuídos | Arquitetura

Definição

Backpressure é um mecanismo de controle de fluxo onde o consumidor regula a velocidade do produtor, evitando que o sistema receba mais dados do que consegue processar.

Em termos práticos:

  • O produtor envia dados
  • O consumidor processa
  • Se o consumidor não acompanha → ele sinaliza para reduzir o ritmo

Problema que o Backpressure resolve

Em arquiteturas distribuídas e assíncronas, é comum existir desequilíbrio entre:

  • taxa de entrada (input)
  • capacidade de processamento (throughput)

Sem controle:

  • crescimento descontrolado de filas
  • aumento de latência
  • consumo excessivo de memória
  • falha em cascata

Comportamento do sistema

Sem backpressure

  • produtor envia continuamente
  • consumidor acumula backlog
  • fila cresce indefinidamente

Com backpressure

  • consumidor limita o consumo
  • produtor desacelera
  • sistema mantém estabilidade

Estratégias comuns

Controle por fila

  • limitar tamanho da fila
  • bloquear produção ao atingir limite

Rate limiting

  • limitar requisições por segundo
  • geralmente aplicado no API Gateway

Pull-based consumption

  • consumidor busca dados quando está pronto
  • comum em Kafka e streams

Buffer com capacidade limitada

  • estrutura intermediária controla fluxo
  • quando cheia → bloqueia ou descarta

Backpressure em arquiteturas modernas

Backpressure aparece em:

  • mensageria (RabbitMQ, Kafka)
  • APIs (rate limiting, throttling)
  • streaming (Reactive Streams)
  • processamento assíncrono

Ele é essencial para:

  • escalabilidade
  • estabilidade operacional
  • previsibilidade de performance

Exemplo prático em C# usando Channel

O Channel do .NET implementa backpressure nativamente ao permitir limitar a capacidade do buffer.

Cenário

  • produtor gera dados rapidamente
  • consumidor processa mais lentamente
  • canal limita o fluxo

Código

using System;
using System.Threading.Channels;
using System.Threading.Tasks;

class Program
{
static async Task Main()
{
var channel = Channel.CreateBounded<int>(new BoundedChannelOptions(5)
{
FullMode = BoundedChannelFullMode.Wait // aplica backpressure
});

var producer = ProduceAsync(channel.Writer);
var consumer = ConsumeAsync(channel.Reader);

await Task.WhenAll(producer, consumer);
}

static async Task ProduceAsync(ChannelWriter<int> writer)
{
for (int i = 0; i < 20; i++)
{
Console.WriteLine($"Produzindo: {i}");
await writer.WriteAsync(i); // bloqueia se o buffer estiver cheio
}

writer.Complete();
}

static async Task ConsumeAsync(ChannelReader<int> reader)
{
await foreach (var item in reader.ReadAllAsync())
{
Console.WriteLine($"Consumindo: {item}");
await Task.Delay(1000); // simula processamento lento
}
}
}

Comportamento do exemplo

  • capacidade do buffer = 5

  • produtor tenta enviar 20 itens rapidamente

  • quando o buffer enche:

    • WriteAsync aguarda
    • produtor desacelera automaticamente

Isso caracteriza backpressure, pois:

  • o consumidor controla o ritmo
  • o sistema não cresce indefinidamente

Pontos importantes

  • backpressure não elimina carga, apenas controla

  • deve ser combinado com:

    • escalabilidade horizontal
    • retry policies
    • circuit breaker
  • pode ser implementado em diferentes camadas:

    • infraestrutura
    • aplicação
    • gateway