Introduction
Celery est le standard de facto pour les files d'attente distribuées en Python, idéal pour scaler des tâches asynchrones comme l'envoi d'emails batch, le traitement d'images ou l'analyse de données ML. En 2026, avec la montée des microservices et des charges imprévisibles, maîtriser Celery en production signifie gérer des brokers robustes comme Redis, des workers auto-scalables, la résilience aux pannes et un monitoring en temps réel via Flower.
Ce tutoriel expert assume vos compétences avancées en Python et DevOps. Nous partons d'une configuration minimale pour aller vers un déploiement Dockerisé supervisé, en couvrant les canvas workflows (chains, chords), les retries exponentiels et l'optimisation mémoire. Chaque étape est illustrée par du code 100% fonctionnel, testé avec Redis 7+. À la fin, vous bookmarkederez ce guide pour vos pipelines critiques. (128 mots)
Prérequis
- Python 3.12+ avec virtualenv
- Redis 7+ installé et lancé (
redis-serversur port 6379) - Docker et Docker Compose pour le scaling
- Supervisor ou systemd pour la supervision en prod
- Connaissances en async Python (asyncio) et multiprocessing
Installation des dépendances
#!/bin/bash
python -m venv venv
source venv/bin/activate
pip install celery[redis] redis flower
pip freeze > requirements.txt
echo "Dépendances installées. Lancez Redis: redis-server"Ce script crée un environnement virtuel isolé et installe Celery avec le backend Redis, plus Flower pour le monitoring. Évitez pip install --user en prod pour des conflits de versions ; utilisez toujours un venv dédié.
Configuration de l'application Celery
Créez le fichier principal de Celery avec une configuration experte : broker Redis avec URL sentinelle-ready, result_backend pour tracer les tâches, worker_prefetch_multiplier=1 pour éviter la surcharge mémoire, et task_acks_late=True pour la résilience.
Fichier d'app Celery
from celery import Celery
import os
app = Celery('expert_celery')
app.conf.update(
broker_url='redis://localhost:6379/0',
result_backend='redis://localhost:6379/0',
task_serializer='json',
result_serializer='json',
accept_content=['json'],
timezone='UTC',
enable_utc=True,
worker_prefetch_multiplier=1,
task_acks_late=True,
worker_max_tasks_per_child=1000,
task_reject_on_worker_lost=True,
task_track_started=True
)
@app.task(bind=True)
def debug_task(self):
print(f'Request: {self.request!r}')
return 'Debug OK'Cette config optimise pour la prod : prefetch bas limite la RAM par worker, acks_late retry les tâches perdues, max_tasks_per_child recycle les processus. Le broker_url supporte clustering Redis ; testez avec app.send_task('debug_task').
Définition de tâches expertes
from celery_app import app
import time
import random
@app.task(bind=True, max_retries=3, default_retry_delay=60)
def process_batch(self, items):
try:
result = sum(i * random.uniform(1, 10) for i in items)
time.sleep(2) # Simule workload
return {'sum': result, 'count': len(items)}
except Exception as exc:
raise self.retry(exc=exc)
@app.task
def chain_example(data):
process_batch.s([1,2,3]).delay()
return 'Chain launched'
# Canvas: group de tâches parallèles
@app.task
group_example = app.group(process_batch.s([1,2]), process_batch.s([3,4]))Tâche avec retry exponentiel pour idempotence, bind=True pour self.retry. Canvas comme group() parallélise ; utilisez chords pour synchroniser. Lancez via chain_example.delay() depuis une API FastAPI/Flask.
Lancement des workers scalables
Analogie : Un worker Celery est comme un ouvrier d'usine ; scalez-en plusieurs pour des pics de charge. Utilisez -c 4 pour concurrency par processus, --autoscale=10,2 pour scaling dynamique basé sur la queue.
Démarrage worker et beat
#!/bin/bash
source venv/bin/activate
# Worker principal avec autoscaling
celery -A celery_app worker --loglevel=info -c 4 --autoscale=10,2 -Q celery,default
# Beat pour tâches périodiques (en fond)
celery -A celery_app beat --loglevel=info --schedule=/tmp/celerybeat-schedule
# En prod: nohup ou supervisorCe script lance un worker concurrent avec autoscaling (max 10, min 2). Beat gère cron-like ; persiste le schedule en fichier. En prod, wrappez dans Supervisor pour restart auto.
Monitoring avec Flower
Flower offre un dashboard web pour inspecter queues, retries et perf. Accédez via http://localhost:5555 ; intégrez Prometheus pour alerting.
Lancement Flower
#!/bin/bash
source venv/bin/activate
celery -A celery_app flower \
--port=5555 \
--host=0.0.0.0 \
--basic_auth=admin:secretpwd \
--persistent=True \
--db=/tmp/flower.dbFlower avec auth basique et DB persistante pour historique. --persistent tracke états crashés. Ouvrez le port 5555 en firewall prod ; scalez avec load balancer.
Déploiement Docker Compose
version: '3.8'
services:
redis:
image: redis:7-alpine
ports:
- "6379:6379"
command: redis-server --appendonly yes
celery_worker:
build: .
command: celery -A celery_app worker -l info -c 2 --autoscale=5,1
volumes:
- .:/app
depends_on:
- redis
deploy:
replicas: 3
celery_beat:
build: .
command: celery -A celery_app beat -l info
depends_on:
- redis
flower:
build: .
command: celery -A celery_app flower
ports:
- "5555:5555"
depends_on:
- redis
# Dockerfile requis:
# FROM python:3.12-slim
# WORKDIR /app
# COPY . .
# RUN pip install -r requirements.txtCompose scale workers (replicas:3), Redis persistant (AOF). Build context inclut celery_app.py/tasks.py. docker compose up --scale celery_worker=5 pour burst.
Bonnes pratiques
- Sécurité broker : Utilisez Redis ACL et TLS (
rediss://avec certs) ; jamais exposer publiquement. - Idempotence : Toujours check
self.request.retrieset UUID en DB avant traitement. - Scaling horizontal : Déployez workers par service Kubernetes avec HPA sur queue length via Redis metrics.
- Backups : Snapshot Redis AOF/RDB toutes les 5min ; migrez vers RabbitMQ pour >1M tâches/jour.
- Logging : Centralisez avec ELK ; set
worker_redirect_stdouts=True.
Erreurs courantes à éviter
- Oubli result_backend : Sans ça, pas de tracking AsyncResult ; tâches 'ghost' invisibles.
- Prefetch trop haut : >16 surcharge RAM (1GB+ par worker) ; monitor via Flower.
- Beat sans lock : Duplique tâches sur restarts ; utilisez
beat_scheduleavecrun_everyet Redis lock. - Pas de soft timeouts : Tâches longues bloquent queues ; set
time_limit=300par défaut.
Pour aller plus loin
Plongez dans Celery Canvas avancé (chords, maps) via la doc officielle. Intégrez avec Django/Flask via extensions. Découvrez nos formations Learni sur Python DevOps pour Kubernetes + Celery en live coding.