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:
WriteAsyncaguarda- 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