Aula 18 - Tarefas em Segundo Plano com Celery e Redis 🐇
Objetivo Pedagógico
Objetivo: Arquitetura assíncrona de processamento em segundo plano (background jobs), filas de mensageria com Celery, agendamento de tarefas e retry com backoff.
📑 1. Fundamentos Teóricos & Análise Técnica
Tarefas de longa duração (como processamento e conversão de vídeos, treinamento de modelos de machine learning, geração de relatórios fiscais em PDF e disparo em lote de e-mails) nunca devem ser executadas síncronamente na thread da requisição HTTP. Reter a resposta por mais de alguns segundos exaure o pool de conexões do servidor e degrada severamente a experiência do usuário.
A solução arquitetural padrão na indústria Python consiste em desacoplar o produtor do consumidor via Filas de Mensagens (Task Queues) com Celery e Redis/RabbitMQ: 1. Produtor (Web API): Recebe a solicitação do usuário, despacha um evento de trabalho (job) para a fila com task.delay(*args) e retorna instantaneamente HTTP 202 Accepted com o ID da tarefa. 2. Message Broker (Redis/RabbitMQ): Armazena as mensagens em memória de forma ordenada e distribuída. 3. Workers (Trabalhadores Celery): Processos em nós independentes que retiram mensagens da fila e executam a computação pesada em background. 4. Result Backend: Armazenamento opcional para consulta posterior do status e resultado da execução.
📐 Arquitetura Conceitual & Diagrama de Fluxo
sequenceDiagram
autonumber
actor Client as Cliente Web
participant API as FastAPI Web Server
participant Broker as Redis Message Broker
participant Worker as Celery Worker Process
Client->>API: POST /reports/generate
API->>Broker: Despacha Mensagem (task.delay)
API-->>Client: 202 Accepted (job_id: "xyz-123")
Broker->>Worker: Entrega Mensagem para Execução
Note over Worker: Processamento Pesado em Segundo Plano (15s)
Worker->>Broker: Atualiza Status: "SUCCESS"
Client->>API: GET /reports/status/xyz-123
API-->>Client: Retorna Relatório Concluído! 🔍 Pilares e Diretrizes Técnicas
Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Desacoplamento Assíncrono: O servidor web responde em milissegundos enquanto a tarefa consome os minutos necessários no worker. - Políticas de Retry Automático: Configuração de tentativas com backoff exponencial para lidar com falhas transitórias de rede. - Limitação de Concorrência: Controle fino do número de processos filhos (--concurrency) para não esgotar a RAM do servidor. - Tarefas Agendadas com Celery Beat: Substituto profissional do Cron para rotinas periódicas de limpeza e consolidação noturna.
🛠️ 2. Implementação Prática em Python, Celery e Redis Message Broker
Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:
// celery_tasks.py (Definição de Tarefas com Retry e Backoff)
from celery import Celery
import time
# Configuração do Celery com Redis como Broker e Backend
celery_app = Celery(
"tasks",
broker="redis://localhost:6379/0",
backend="redis://localhost:6379/1"
)
@celery_app.task(
bind=True,
max_retries=3,
default_retry_delay=5,
autoretry_for=(Exception,),
retry_backoff=True
)
def process_pdf_report(self, user_id: str, report_data: dict) -> dict:
try:
print(f"[Worker] Iniciando geração de PDF para usuário: {user_id}")
time.sleep(10) # Simula renderização pesada
print(f"[Worker] PDF gerado com sucesso!")
return {"user_id": user_id, "status": "COMPLETED", "file_url": f"/files/{user_id}.pdf"}
except Exception as exc:
print(f"[Worker] Falha temporária. Agendando retry: {exc}")
raise self.retry(exc=exc)
💡 Análise Passo a Passo do Código
- Parâmetro bind=True: Permite que a função acesse a instância da própria tarefa (
self) para inspecionar tentativas e disparar retries. - Retry Backoff Exponencial:
retry_backoff=Truedobra o tempo de espera a cada nova tentativa (5s, 10s, 20s), evitando sobrecarregar serviços externos. - Result Backend Dedicado: A URL
redis://localhost:6379/1armazena o dicionário retornado para consulta posterior pela API.
🎯 3. Próximos Passos & Sequência Didática
-
Slides da Aula
-
Quiz de Fixação
-
Exercícios Práticos
-
Desafio de Projeto