参考
官方文档Celery在Django上
官方文档Celery
Celery中文文档
Github地址
Celery全面学习笔记
分布式任务队列Celery入门与进阶
一、概要
Celery是由Python开发、简单、灵活、可靠的分布式任务队列,其本质是生产者消费者模型,生产者发送任务到消息队列,消费者负责处理任务。
Celery侧重于实时操作,但对调度支持也很好,其每天可以处理数以百万计的任务。特点:
- 简单:熟悉celery的工作流程后,配置使用简单
- 高可用:当任务执行失败或执行过程中发生连接中断,celery会自动尝试重新执行任务
- 快速:一个单进程的celery每分钟可处理上百万个任务
- 灵活:几乎celery的各个组件都可以被扩展及自定制
应用场景举例:
- web应用:当用户在网站进行某个操作需要很长时间完成时,我们可以将这种操作交给Celery执行,直接返回给用户,等到Celery执行完成以后通知用户,大大提好网站的并发以及用户的体验感。比如发送短信/邮件、消息推送、音视频处理等
- 任务场景:比如在运维场景下需要批量在几百台机器执行某些命令或者任务,此时Celery可以轻松搞定。
- 定时任务:向定时导数据报表、定时发送通知类似场景,虽然Linux的计划任务可以帮我实现,但是非常不利于管理,而Celery可以提供管理接口和丰富的API。
Celery由以下四部分构成:任务模块(Task)、消息中间件(Broker)、任务执行单元Worker、结果存储(Backend)
- 任务模块Task:包含异步任务和定时任务,异步任务通常在业务逻辑中被触发并发往任务队列,而定时任务由Celery Beat进程周期性的将任务发往任务队列
- 消息中间件Broker:即为任务调度队列,接收任务生产者发来的消息(即任务),将任务存入队列。Celery本身不提供队列服务,官方提供了很多备选方案,支持RabbitMQ、Redis、Amazon SQS等,官方推荐RabbitMQ。
- 任务执行单元Worker:Worker是任务执行单元,负责从消息队列中取出任务执行,它可以启动一个或者多个,也可以启动在不同的机器节点,这就是其实现分布式的核心。实时监控消息队列,获取队列中调度的任务并执行它。
- 结果存储Backend:用于存储任务的执行结果。官方提供了诸多的存储方式支持:RabbitMQ、 Redis、Memcached、SQLAlchemy、Django ORM、Apache Cassandra、Elasticsearch
如图:
工作原理:
- 任务模块Task包含异步任务和定时任务。其中,异步任务通常在业务逻辑中被触发并发往消息队列,而定时任务由Celery Beat进程周期性地将任务发往消息队列;
- 任务执行单元Worker实时监视消息队列获取队列中的任务执行;
- Woker执行完任务后将结果保存在Backend中;
如图:
二、环境
- Python:3.7
- Django:2.2.4
- Celery:4.3
注意:Celery 4.x和3.x版本相差很大,建议使用4.x,另外,如果是Django 1.8之前的版本,只能使用Celery 3.x
三、依赖
需要安装的依赖有:
pip install celery
pip install redis
# 或者是直接:pip install "celery[redis]"
pip install mysqlclient
pip install django-celery-results
以上的依赖中,只有Celery是必须的,其他的依赖都不是必须,如下:
- redis:非必须,默认Celery是使用RabbitMQ作为Broker中间人的并且默认安装好RabbitMQ依赖了,我自己习惯用Redis,所以需要安装Redis依赖
- mysqlclient:非必须,默认Celery是不保存任务结果的,如果想要查看任务的结果并且可以保存到数据库中,所以必须安装mysqlclient连接数据库
- django-celery-results:非必须,默认Celery是不保存任务结果的,如果想要查看任务的结果并且保存到数据库中,就必须安装该依赖,如果不想保存到数据库的话,也可以使用Redis来进行保存
中间人:
- RabbitMQ:默认
- Redis
- Amazon SQS
注意:Celery之前的版本是支持以数据库作为中间人的,但是4.x不支持数据库作为中间人,具体可以参考 官方文档
注意:有一些教程使用django-celery这个库来安装celery,这个是Celery3.x的版本,4.x已经不建议使用这个了
四、初始化
1. 新建一个应用
新建一个应用,应用名随意,这里的应用名为tasks
python manage startapp tasks
setting.py中增加应用:
INSTALLED_APPS = (
...,
'tasks',
'django_celery_results',
)
执行迁移
python manage.py migrate django_celery_results
2. setting.py同级目录修改init.py
setting.py同级目录修改__init__.py:
from __future__ import absolute_import, unicode_literals
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app
__all__ = ('celery_app',)
3. setting.py同级目录新建celery.py
setting.py同级目录新建celery.py:
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from django.conf import settings
# 获取当前文件夹名,即为该Django的