-
Prefira RabbitMQ ou Redis como broker (nunca use banco de dados relacional como broker de produção)
-
Não use objetos complexos como parametros em tarefas. Exemplo: Evite objetos Django model:
# Bom @app.task def my_task(user_id): user = User.objects.get(id=user_id) print(user.name) # ...
# Ruim @app.task def my_task(user): print(user.name) # ...
-
Não espere por outras tarefas dentro de uma tarefa.
-
Prefira tarefas indempotentes.
- "Em matemática e ciência da computação, a idempotência é a propriedade que algumas operações têm de poderem ser aplicadas várias vezes sem que o valor do resultado se altere após a aplicação inicial." - Wikipedia
-
Prefira tarefas atômicas.
- "Transação Atômica, em ciência da computação, é uma operação, ou conjunto de operações, em uma base de dados, ou em qualquer outro sistema computacional, que deve ser executada completamente em caso de sucesso, ou ser abortada completamente em caso de erro." - Wikipedia
-
Tente novamente quando possível. Mas tenha certeza que as tarefas são indempotentes e atômicos antes de fazê-lo. (Retrying)
-
Defina
retry_limit
para evitar tarefas quebradas de fazer tentativas infinitas. -
Exponenciamente caia fora se coisas parecerem que não vão ser corrigidos logo. Jogue um fator randômico para evitar confusão de serviços.
def exponencial_backoff(task_self): minutes = task_self.default_retry_delay / 60 rand = random.uniform(minutes, minutes * 1.3) return int(rand ** task_self.request.retries) * 60 # na tarefa raise self.retry(exc=e, countdown=exponencial_backoff(self))
- Para tarefas que requere alto nível de confiabilidade, use
acks_late
em combinação comretry
. Novamente, tenha certeza de que são tarefas idempotentes e atômicas. (Should I use retry or acks_late?) - Defina tempos de limite duros e suaves. Recupere graciosamente se as coisas demorarem mais tempo que o esperado.
from celery.exceptions import SoftTimeLimitExceeded @app.task(task_time_limit=60, task_soft_time_limit=45) def my_task(): try: something_possibly_long() except SoftTimeLimitExceeded: recover()
- Para tarefas que requere alto nível de confiabilidade, use
-
Use múltiplas filas para ter mais controle sobre a taxa de transferência e gerar mais escalabilidade. (Routing Tasks)
-
Estenda a classe de tarefa base para definir comportamentos padrão. (Custom Task Classes)
-
Use recursos de
canvas
para controlar fluxos de tarefas e lidar com concorrência. (Canvas: Designing Work-flows)
- Faça logging na medida do possível. Use
get_task_logger
para automaticamente adicionar o nome e o id único da sua task aos logs. - No caso de falha, tenha certeza de que
stack traces
sejam logados e que pessoas sejam notificadas (serviços como Sentry é uma boa idéia). - Monitore atividades usando Flower. (Flower: Real-time Celery web-monitor)
- Use
task_aways_eager
para testar suas tarefas que estão sendo chamadas.
- Celery: an overview of the architecture and how it works por Vinta
- Celery in the wild: tips and tricks to run async tasks in the real world por Vinta
- Dealing with resource-consuming tasks on Celery por Vinta
- Dicas e Boas Práticas da documentação oficial.
- Task Queues por Full Stack Python
- Flower: Real-time Celery web-monitor da documentação oficial
- Celery Best Practices: practical approach por Adil
- 3 GOTCHAS FOR CELERY do Wiredcraft
- CELERY * [ ] BEST PRACTICES por Deni Bertovic
- Hacker News thread on the above post
- [video] Painting on a Distributed Canvas: An Advanced Guide to Celery Workflows por David Gouldin
- Celery in Production por Dan Poirier do Caktus Group
- [video] Implementing Celery, Lessons Learned por Michael Robellard
- [video] Advanced Celery por Ask Solem Hoel
- Celery Best Practices por Balthazar Rouberol