Filas e workers: processamento assíncrono

1. Fundamentos de Filas e Workers

1.1. Definição

Filas de mensagens são estruturas de dados que armazenam temporariamente mensagens trocadas entre produtores e consumidores. Workers são processos ou serviços que consomem essas mensagens, executando tarefas de forma assíncrona.

1.2. Diferença entre processamento síncrono e assíncrono

No processamento síncrono, o cliente aguarda a resposta imediatamente. No assíncrono, o cliente envia a requisição e continua sua execução, enquanto o worker processa em segundo plano.

text
// Síncrono
Cliente -> API -> Processamento -> Resposta (bloqueante)

// Assíncrono
Cliente -> API -> Fila -> Worker -> Processamento (não bloqueante)
         <- 202 Accepted

1.3. Papel da fila como buffer

A fila atua como amortecedor entre picos de requisição e capacidade de processamento, evitando perda de dados e sobrecarga do sistema.

2. Arquitetura e Componentes de um Sistema de Filas

2.1. Produtores, filas e consumidores

text
[Produtor A] -> [Fila Principal] -> [Worker 1]
[Produtor B] -> [Fila Principal] -> [Worker 2]
[Produtor C] -> [Fila Principal] -> [Worker 3]

2.2. Brokers de mensagens populares

  • RabbitMQ: broker robusto com suporte a AMQP, roteamento flexível e confiabilidade
  • Apache Kafka: plataforma distribuída para streaming de eventos, alta throughput e persistência
  • AWS SQS: serviço gerenciado na nuvem, escalável e com garantias de entrega

2.3. Padrões de entrega

Ponto-a-ponto: uma mensagem é consumida por um único worker.

Publish-subscribe: uma mensagem é entregue a múltiplos consumidores.

text
// Ponto-a-ponto
[Produtor] -> [Fila] -> [Worker A] (consome)

// Publish-subscribe
[Produtor] -> [Exchange] -> [Fila 1] -> [Worker A]
                          -> [Fila 2] -> [Worker B]
                          -> [Fila 3] -> [Worker C]

3. Estratégias de Roteamento e Priorização

3.1. Filas únicas vs. múltiplas

Filas únicas simplificam a gestão, mas podem causar contenção. Filas múltiplas por tipo de tarefa permitem isolamento e priorização.

text
// Fila única
[Pedidos, Emails, Relatórios] -> [Worker genérico]

// Filas múltiplas
[Pedidos] -> [Worker pedidos]
[Emails] -> [Worker emails]
[Relatórios] -> [Worker relatórios]

3.2. Prioridade de mensagens

text
// Mensagens com prioridade
[Fila] -> Ordenação por prioridade (1-10)
[Worker] consome mensagens de maior prioridade primeiro

3.3. Roteamento baseado em chaves

text
[Exchange] -> Routing Key "pedido.criado" -> [Fila Pedidos]
           -> Routing Key "email.envio"   -> [Fila Emails]
           -> Routing Key "relatorio.*"   -> [Fila Relatórios]

4. Garantias de Entrega e Confiabilidade

4.1. Modos de entrega

  • At-least-once: a mensagem é entregue pelo menos uma vez (pode duplicar)
  • At-most-once: a mensagem é entregue no máximo uma vez (pode perder)
  • Exactly-once: a mensagem é entregue exatamente uma vez (mais complexo)

4.2. Acknowledgments e Dead-Letter Queues

text
[Worker] -> Processa mensagem -> ACK -> Remove da fila
[Worker] -> Falha no processamento -> NACK -> DLQ

DLQ -> [Fila de mensagens mortas] -> Análise manual ou reprocessamento

4.3. Idempotência e reprocessamento

text
// Exemplo de idempotência
function processarPedido(pedidoId, dados) {
    if (pedidoJaProcessado(pedidoId)) {
        return; // Ignora duplicatas
    }
    salvarPedido(dados);
    marcarComoProcessado(pedidoId);
}

5. Escalabilidade e Performance dos Workers

5.1. Escalabilidade horizontal

text
[Fila] -> [Worker 1]
       -> [Worker 2]
       -> [Worker 3]
       -> [Worker N]

5.2. Controle de concorrência

Prefetch count define quantas mensagens um worker pode receber simultaneamente.

text
// Configuração de prefetch
prefetch_count = 10 // Worker recebe até 10 mensagens de uma vez

5.3. Auto-scaling baseado em tamanho da fila

text
Se tamanho_fila > 1000:
    adicionar_workers(2)
Se tamanho_fila < 100:
    remover_workers(1)

6. Padrões de Projeto com Filas

6.1. Work Queue

Distribuição balanceada de tarefas entre workers.

text
[Fila] -> Round-robin entre workers
       -> [Worker A] -> Tarefa 1
       -> [Worker B] -> Tarefa 2
       -> [Worker C] -> Tarefa 3

6.2. Fan-out

Broadcasting de mensagens para múltiplos consumidores.

text
[Exchange Fanout] -> [Fila Notificações] -> [Worker Email]
                  -> [Fila Logs]         -> [Worker Log]
                  -> [Fila Analytics]    -> [Worker Analytics]

6.3. Saga Pattern

Coordenação de transações distribuídas via filas.

text
[Pedido Criado] -> [Fila] -> [Worker Pagamento]
[Pagamento OK]  -> [Fila] -> [Worker Estoque]
[Estoque OK]    -> [Fila] -> [Worker Entrega]

[Falha Pagamento] -> [Fila] -> [Worker Compensação]

7. Monitoramento e Observabilidade

7.1. Métricas essenciais

text
Métricas a monitorar:
- Latência de processamento (ms)
- Throughput (mensagens/segundo)
- Tamanho da fila (mensagens pendentes)
- Taxa de erro (%)
- Workers ativos
- Mensagens em DLQ

7.2. Rastreamento distribuído

text
// Correlation ID para rastrear fluxo
Mensagem: {
    "correlation_id": "abc-123",
    "payload": { ... },
    "timestamp": "2024-01-01T00:00:00Z"
}

7.3. Alertas e escalonamento

text
Alertas:
- Tamanho_fila > 5000 por 5 minutos -> Escalar workers
- Taxa_erro > 5% -> Notificar equipe
- Workers_inativos > 0 -> Reiniciar workers
- DLQ > 100 mensagens -> Revisar código

8. Trade-offs e Considerações Finais

8.1. Complexidade operacional vs. resiliência

Filas aumentam a complexidade operacional, mas oferecem:
- Tolerância a falhas
- Desacoplamento entre sistemas
- Capacidade de absorver picos
- Processamento assíncrono

8.2. Quando não usar filas

  • Requisitos de latência abaixo de 10ms
  • Processamento simples e rápido
  • Sistemas com baixo volume de dados
  • Operações que exigem resposta imediata

8.3. Relação com temas vizinhos

  • Cache: reduz carga em filas para dados frequentemente acessados
  • CDN: distribui conteúdo estático, reduzindo necessidade de processamento
  • Sharding: particiona filas para escalabilidade horizontal
  • Escalabilidade: filas permitem escalar workers independentemente

Referências