分布式任务队列 Celery —— 应用基础
2018-01-28 17:55 云物互联 阅读(554) 评论(0) 编辑 收藏 举报目录
前文列表
分布式任务队列 Celery
分布式任务队列 Celery —— 详解工作流
前言
紧接前文,继续看 Celery 应用基础,下列样例依旧从前文 proj 中进行修改。
Celery 的周期(定时)任务
Celery 周期任务功能由 Beat 任务调度器模块支撑,Beat 是一个服务进程,负责周期性启动 beat_schedule 中定义的任务。
e.g.
# filename: app_factory.py
from __future__ import absolute_import
from celery import Celery
from kombu import Queue, Exchange
def make_app():
app = Celery('proj')
app.config_from_object('proj.celeryconfig')
default_exchange = Exchange('default', type='direct')
web_exchange = Exchange('task', type='direct')
app.conf.task_default_queue = 'default'
app.conf.task_default_exchange = 'default'
app.conf.task_default_routing_key = 'default'
app.conf.task_queues = (
Queue('default', default_exchange, routing_key='default'),
Queue('high_queue', web_exchange, routing_key='hign_task'),
Queue('low_queue', web_exchange, routing_key='low_task'),
)
# 设定 Beat 时区,默认为 UTC 时区
app.conf.timezone = 'Asia/Shanghai’
# 在 beat_schedule 中声明周期任务
app.conf.beat_schedule = {
# 周期任务 Friendly Name
'periodic_task_add': {
# 任务全路径
'task': 'proj.task.tasks.add’,
# 周期时间
'schedule': 3.0,
# 指定任务所需的参数
'args': (2, 2)
},
}
return app
使用 -B 选择,表示启动 Celery Worker 服务进程的同时启动 Beat 模块。
NOTE 1:Beat 会把周期任务的时间表存储在 celerybeat-schedule 文件,在执行指令的当前目录生成。当 timezone 发生改变时,Beat 会根据 celerybeat-schedule 的内容自动调整计时方式。
NOTE 2:Beat 也支持 crontab 计时方式,十分简单易用。
e.g.
# filename: app_factory.py
from celery.schedules import crontab
…
app.conf.beat_schedule = {
'periodic_task_add': {
'task': 'proj.task.tasks.add’,
# 每隔一分钟周期执行
'schedule': crontab(minute='*/1'),
'args': (2, 2)
},
}
Celery 的同步调用
Task.get 方法处理用于获取任务的执行结果之外,还能够用于实现 Celery 同步调用,以满足更多的应用场景。
e.g.
# filename: tasks.py
import time
from proj.celery import app
@app.task
def add(x, y, debug=False):
# Test sync invoke.
time.sleep(10)
for i in xrange(10):
print("Warting: %s s" % i)
if debug:
print("x: %s; y: %s" % (x, y))
return x + y
同步调用任务 add
>>> from proj.task.tasks import add
>>> add.delay(2, 2).get()
4
因为直接调用了 get 方法,所以进程会被阻塞知道任务 add 返回结果为止。
Celery 结果储存
如果你对任务执行的结果非常关注,那么你可以使用数据库(e.g. Redis)来充当 Backend,从而将执行结果持久化。
e.g.
# 执行一个任务,并取得任务 id
>>> from proj.task.tasks import add
>>> result = add.delay(2, 2)
>>> result.status
u’SUCCESS'
>>> result.get()
4
>>> result.id
'65cee5e0-5f4f-4d2b-b52f-6904e7f2b6ab’
进入 Redis 数据库,查看该任务对应的记录。
root@aju-test-env:~# redis-cli
127.0.0.1:6379>
# 查看 Redis 所有的 keys
127.0.0.1:6379> keys *
1) "celery-task-meta-da3f6f3d-f977-4b39-a795-eaa89aca03ec"
2) "celery-task-meta-38437d5c-ebd8-442c-8605-435a48853085”
...
35) "celery-task-meta-65cee5e0-5f4f-4d2b-b52f-6904e7f2b6ab"
...
# 通过任务 id,可以定位出任务在 Redis 中的 value
127.0.0.1:6379> GET 'celery-task-meta-65cee5e0-5f4f-4d2b-b52f-6904e7f2b6ab'
"{\"status\": \"SUCCESS\", \"traceback\": null, \"result\": 4, \"task_id\": \"65cee5e0-5f4f-4d2b-b52f-6904e7f2b6ab\", \"children\": []}"
Celery 的监控
Celery Flower 是 Celery 官方推荐的监控工具,借助于 Celery Events 接口,Flower 能够实时监控 Celery 的 Worker、Tasks、Broker、并发池等重要对象。
- 安装 Flower
$ pip install flower
- 开启 Celery Events
celery worker -A proj -E -l info
- 开启 RabbitMQ Management Plugin
$ rabbitmq-plugins enable rabbitmq_management
$ service rabbitmq-server restart
- 启动 Flower,并指定 broker URL
>nbsp;celery flower -l info --broker_api=http://guest:guest@<rabbitmq_server_ip>:15672/api/
- 访问 Flower Web,浏览器打开
http://<flower_server_ip>:5555/dashboard
Celery 的调试
Celery 借助 telnet 可以支持远程 pdb 调试,非常方便。
# filename: tasks.py
from proj.celery import app
from celery.contrib import rdb
@app.task
def add(x, y):
# 设置断点
rdb.set_trace()
return x + y
使用 celery.contrib
的 rdb 来设置断点,然后重启 Celery Worker 服务。
可以看见日志中提示了 telnet 远程连接的地址,所以打开另外一个终端,执行 telnet 指令即可完成连接,进入到非常熟悉的 pdb shell。