代码改变世界

分布式任务队列 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。

这里写图片描述