Celery 是一个简单、灵活且可靠的,处理大量消息的分布式系统,它是一个专注于实时处理的任务队列, 同时也支持任务调度。Celery 中有两个比较关键的概念:
- Worker: worker 是一个独立的进程,它持续监视队列中是否有需要处理的任务;
- Broker: broker 也被称为中间人,broker 负责协调客户端和 worker 的沟通。客户端向队列添加消息,broker 负责把消息派发给 worker。
安装 Celery
直接使用 python 工具 pip 安装:
$ pip install celery
安装 Broker
Celery 支持多种 broker, 但主要以 RabbitMQ 和 Redis 为主。在 RabbitMQ 和 Redis之间,该如何选择呢?
RabbitMQ is feature-complete, stable, durable and easy to install. It’s an excellent choice for a production environment.
Redis is also feature-complete, but is more susceptible to data loss in the event of abrupt termination or power failures.
Celery 官方明确表示推荐在生产环境下使用 RabbitMQ,Redis 存在丢数据的问题。所以如果你的业务可以容忍 worker crash 或者电源故障导致的任务丢失,采用 Redis 是个不错的选择,本篇就以 Redis 为例来介绍。
Celery 对于 Redis 的支持需要安装相关的依赖,以下命令可以同时安装 Celery 和 Redis 相关的依赖,但是 redis server 还是必须单独安装的。
$ pip install -U celery[redis] # -U 的意思是把所有指定的包都升级到最新的版本
Celery 的配置和使用
Celery 本身的配置项是很多的,但是如果要让它跑起来,只需要加一行配置:
BROKER_URL = 'redis://localhost:6379//'
这一行就是告诉 celery broker 的地址和选择的 redis db,默认是 0。接下来用个很简单的例子来介绍 celery 是如何使用的:
# tasks.py
from celery import Celery
app = Celery('tasks', broker='redis://localhost//')
@app.task
def add(x, y):
return x + y
以上创建了一个 celery 的实例 app,可以通过它来创建任务和管理 workers。
接下来运行 celery worker,通过它来监听是否有任务要处理:
$ celery -A tasks worker -l info
通过 celery worker –help 查看更多参数选项
接着再打开一个 shell 窗口,进入 python 控制台去调用 add 任务:
>>> from tasks import add
>>> add.delay(1, 2)
<AsyncResult: 42ade14e-c7ed-4b8d-894c-1ca1ec7ca192>
发现 add 任务并没有返回 3,而是一个对象 AsyncResult,它的作用是被用来检查任务状态,获取任务结果,如果任务失败,它会返回异常信息或者调用栈。
先尝试获取任务的执行结果:
>>> result = add.delay(1, 2)
>>> result.get()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/celery/result.py", line 169, in get
no_ack=no_ack,
File "/usr/local/lib/python2.7/dist-packages/celery/backends/base.py", line 604, in _is_disabled
'No result backend configured. '
NotImplementedError: No result backend configured. Please see the documentation for more information.
报错了:No result backend configured. 错误信息告诉我们没有配置 result backend。因为 celery 会将任务的状态或结果保存在 result backend,result backend 的选择也有很多,本例中依然选用 redis 作为 result backend。
修改 tasks.py 的代码,添加上 result backend 的设置,保存后重启 celery worker。
app = Celery('tasks', backend='redis://localhost', broker='redis://localhost//')
然后重新调用 add task,看看是否获取到了执行结果?
>>> from tasks import add
>>> result = add.delay(1,2)
>>> result.get()
3
正确的获得到了结果!
Flower
flower 是一个 celery 的监控工具,它提供了一个图形用户界面,可以极大的方便我们监控任务的执行过程, 执行细节及历史记录,还提供了统计功能。
安装
$ pip install flower
使用简介
首先通过命令行启动 flower 进程:
$ flower -A tasks --port=5555
然后打开浏览器 http://localhost:5555/
Celery 任务类型
apply_async
调用一个异步任务,这也是最常用的任务类型之一,delay 与它的作用相同,只是 delay 不支持 apply_async 中额外的参数。该方法有几个比较重要的参数,在实际应用中会经常用到:
- countdown: 任务延迟执行的秒数,默认立即执行;
- eta:任务被执行的绝对时间
crontab schedules
from datetime import timedelta
from celery.schedules import crontab
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYBEAT_SCHEDULE = {
# Executes every 30 seconds
'add-every-30-seconds': {
'task': 'tasks.add',
'schedule': timedelta(seconds=30),
'args': (16, 16)
},
# Executes every Monday morning at 7:30 A.M
'add-every-monday-morning': {
'task': 'tasks.add',
'schedule': crontab(hour=7, minute=30, day_of_week=1),
'args': (16, 16)
},
}
要启动定时任务,需要启动一个心跳进程:
$ celery -A tasks beat
或者加上 -B
参数
$ celery -A tasks worker -B -l info