Celery 官网:http://www.celeryproject.org/
Celery 官方文档英文版:http://docs.celeryproject.org/en/latest/index.html
Celery 官方文档中文版:http://docs.jinkan.org/docs/celery/
celery配置:http://docs.jinkan.org/docs/celery/configuration.html#configuration
参考:http://www.cnblogs.com/landpack/p/5564768.html http://blog.csdn.net/happyAnger6/article/details/51408266
http://www.cnblogs.com/forward-wang/p/5970806.html
分布式队列神器 Celery:https://segmentfault.com/a/1190000008022050
celery最佳实践:https://my.oschina.net/siddontang/blog/284107
Celery 分布式任务队列快速入门:http://www.cnblogs.com/alex3714/p/6351797.html
异步任务神器 Celery 快速入门教程:https://blog.csdn.net/chenqiuge1984/article/details/80127446
定时任务管理之python篇celery使用:http://student-lp.iteye.com/blog/2093397
异步任务神器 Celery:http://python.jobbole.com/87086/
celery任务调度框架实践:https://blog.csdn.net/qq_28921653/article/details/79555212
Celery-4.1 用户指南: Monitoring and Management Guide:https://blog.csdn.net/libing_thinking/article/details/78592801
Celery安装及使用:https://blog.csdn.net/u012325060/article/details/79292243
Celery学习笔记(一):https://blog.csdn.net/sdulsj/article/details/73741350
开始使用Celery
使用celery包含三个方面:1. 定义任务函数。2. 运行celery服务。3. 客户应用程序的调用
1.使用 python 虚拟环境 模拟两个不同的 主机。
创建虚拟环境:https://blog.csdn.net/zelinhehe/article/details/79153449
2.创建一个文件 tasks.py输入下列代码:
from celery import Celery
broker = 'redis://127.0.0.1:6379/5'
backend = 'redis://127.0.0.1:6379/6'
app = Celery('tasks', broker=broker, backend=backend)
@app.task
def add(x, y):
return x + y
上述代码导入了celery,然后创建了celery 实例 app,实例化的过程中指定了任务名tasks(和文件名一致),传入了broker和backend。然后创建了一个任务函数add。
3.启动celery服务。在当前命令行终端运行(分别在 env1 和 env2 下执行):
celery -A tasks worker --loglevel=info
此时可以看到输出,其中包括注册的任务。
客户端交互式调试
在当前tasks.py文件下进入python3环境
In [0]:from tasks import add
In [1]: r = add.delay(2, 2)
In [2]: add.delay(2, 2)
Out[2]: <AsyncResult: 6fdb0629-4beb-4eb7-be47-f22be1395e1d>
In [3]: r = add.delay(3, 3)
In [4]: r.re
r.ready r.result r.revoke
In [4]: r.ready()
Out[4]: True
In [6]: r.result
Out[6]: 6
In [7]: r.get()
Out[7]: 6
调用 delay 函数即可启动 add 这个任务。这个函数的效果是发送一条消息到broker中去,这个消息包括要执行的函数、函数的参数以及其他信息,具体的可以看 Celery官方文档。这个时候 worker 会等待 broker 中的消息,一旦收到消息就会立刻执行消息。
现在是在python环境中调用的add函数,实际上通常在应用程序中调用这个方法。
注意:如果把返回值赋值给一个变量,那么原来的应用程序也会被阻塞,需要等待异步任务返回的结果。因此,实际使用中,不需要把结果赋值。
启动了一个任务之后,可以看到之前启动的worker已经开始执行任务了。
使用配置文件
Celery 的配置比较多,可以在 官方配置文档 查询每个配置项的含义。
上述的使用是简单的配置,下面介绍一个更健壮的方式来使用celery。首先创建一个python包,celery服务,姑且命名为proj。目录文件如下:
celery.py
# -*- coding:utf-8 -*-
from __future__ import absolute_import
from celery import Celery
app = Celery('proj',include=['proj.tasks'])
app.config_from_object('proj.config')
if __name__ == '__main__':
app.start()
此时并没有指定broker和backend。
config.py
# -*- coding:utf-8 -*-
from __future__ import absolute_import
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/5'
BROKER_URL = 'redis://127.0.0.1:6379/6'
tasks.py
# -*- coding:utf-8 -*-
from __future__ import absolute_import
from proj.celery import app
@app.task
def add(x,y):
return x + y
使用方法:在 proj 的同一级目录执行 celery:
celery -A proj worker -l info
客户端使用任务直接调用tasks文件的函数即可
任务调度
新建一个proj1的python包
celery.py
# -*- coding:utf-8 -*-
from __future__ import absolute_import
from celery import Celery
app = Celery('proj1',include=['proj1.tasks'])
app.config_from_object('proj1.celeryconfig')
if __name__ == '__main__':
app.start()
tasks.py
# -*- coding:utf-8 -*-
from __future__ import absolute_import
from celery import Celery
app = Celery()
app.config_from_object('celeryconfig')
@app.task
def taskA(x,y):
return x + y
@app.task
def taskB(x,y,z):
return x + y + z
@app.task
def taskC(x,y):
return x + y
上面的tasks.py中,首先定义了一个Celery对象,然后用celeryconfig.py对celery对象进行设置,之后再分别定义了三个task,分别是taskA,taskB和taskC。接下来看一下 celeryconfig.py 文件
celeryconfig.py
# -*- coding:utf-8 -*-
from __future__ import absolute_import
from kombu import Exchange, Queue
BROKER_URL = "redis://192.168.59.129:6379/0"
CELERY_RESULT_BACKEND = "redis://192.168.59.129:6379/0"
# 任务队列分配
CELERY_QUEUES = (
Queue('default',Exchange("default"),routing_key="default"),
Queue('for_task_A',Exchange('for_task_A'),routing_key='task_a'),
Queue('for_task_B',Exchange('for_task_B'),routing_key='task_b')
)
CELERY_ROUTES = {
'tasks.taskA': {"queue": "for_task_A", "routing_key": "task_a"},
'tasks.taskB': {"queue": "for_task_B", "routing_key": "task_b"}
}
在 celeryconfig.py 文件中,首先设置了brokel以及result_backend,接下来定义了三个Message Queue,并且指明了Queue对应的Exchange(当使用Redis作为broker时,Exchange的名字必须和Queue的名字一样)以及routing_key的值。
现在在一台主机上面启动一个worker,这个worker只执行for_task_A队列中的消息,这是通过在启动worker时使用-Q Queue_Name参数指定的。
celery -A tasks worker -l info -n worker.%h -Q for_task_A
然后在另一台主机中,切换路径到工程目录下,执行以下代码来启动taskA:
from tasks improt *
task_A_re = taskA.delay(100,200)
此时task_A消息会立马发送到for_task_A队列中。刚开启任务A的主机立即执行任务。
重复上面的过程,在另外一台机器上启动一个worker专门执行for_task_B中的任务。修改上一步骤的代码,把 taskA 改成 taskB 并执行。
而在 celeryconfig.py 文件中还定义了个默认路由default,没有指定任务route到哪个queue中执行或者指定的route没配置有,执行任务的时候都会自动分配到default队列中。
Scheduler(定时任务,周期性任务)
现实中我们经常会遇到定时任务的需求。而在celery中实现定时任务也很简单。只需要设置celery对象的CELERYBEAT_SCHEDULE属性即可。
celeryconfig.py
# -*- coding:utf-8 -*-
from __future__ import absolute_import
from kombu import Exchange, Queue
BROKER_URL = "redis://192.168.59.129:6379/0"
CELERY_RESULT_BACKEND = "redis://192.168.59.129:6379/0"
# 任务队列分配
CELERY_QUEUES = (
Queue('default',Exchange("default"),routing_key="default"),
Queue('for_task_A',Exchange('for_task_A'),routing_key='task_a'),
Queue('for_task_B',Exchange('for_task_B'),routing_key='task_b')
)
CELERY_ROUTES = {
'tasks.taskA': {"queue": "for_task_A", "routing_key": "task_a"},
'tasks.taskB': {"queue": "for_task_B", "routing_key": "task_b"}
}
# Scheduler (定时任务,周期性任务)
CELERY_TIMEZONE = 'Asia/Shanghai'
from datetime import timedelta
CELERYBEAT_SCHEDULE = {
'taskA_schedule':{
'task': 'proj1.tasks.taskA',
'schedule': timedelta(seconds=5),
'args' : (100,100)
},
'taskB_schedule':{
'task': 'proj1.tasks.taskB',
'schedule': timedelta(seconds=10),
'args' : (100,200,300)
},
'taskC_schedule':{
'task': 'proj1.tasks.taskC',
'schedule': timedelta(seconds=15),
'args' : (200,200)
}
}
定义了3个定时任务,即每隔5s执行taskA任务,参数为(100,100),每隔10s执行taskB任务,参数为(100,200,300),每隔15s执行taskC任务,参数为(200,200).切换到工程同级目录下,通过下列命令启动定时任务: celery -A proj worker -B -l info。使用 beat 参数即可启动定时任务。
crontab定时
celery也能通过crontab模式来设置定时。修改celeryconfig文件
# from datetime import timedelta
#
# CELERYBEAT_SCHEDULE = {
# 'taskA_schedule':{
# 'task': 'proj1.tasks.taskA',
# 'schedule': timedelta(seconds=0.5),
# 'args' : (100,100)
# },
# 'taskB_schedule':{
# 'task': 'proj1.tasks.taskB',
# 'schedule': timedelta(seconds=0.5),
# 'args' : (100,200,300)
# },
# 'taskC_schedule':{
# 'task': 'proj1.tasks.taskC',
# 'schedule': timedelta(seconds=0.5),
# 'args' : (200,200)
# }
# }
from celery.schedules import crontab
CELERYBEAT_SCHEDULE = {
# Executes every Monday morning at 7:30 A.M
'add-every-monday-morning': {
'task': 'tasks.tasksA',
'schedule': crontab(hour=7, minute=30, day_of_week=1),
'args': (16, 16),
},
}
Celery监控和管理以及命令帮助
输入 celery -h 可以看到 celery 的命令和帮助
更详细的帮助可以看官方文档:http://docs.celeryproject.org/en/master/userguide/monitoring.html