异步任务神器 Celery 简明笔记

异步任务

异步任务是web开发被一个很常见的主意。对于部分耗时耗资源的操作,往往由主应用中隔离,通过异步的法执行。简而言之,做一个登记之效力,在用户用邮箱注册成功之后,需要给该邮筒发送一封闭激活邮件。如果直白在应用被,则调用发邮件的长河会赶上网络IO的堵截,比好优雅的法尽管是应用异步任务,应用在业务逻辑中触发一个异步任务。

落实异步任务的家伙发出众多,其规律都是动一个职责队列,比如采用redis生产消费型或披露订阅模式实现一个简单易行的音队列。

除外redis,还可动用另外一个神器—Celery。Celery是一个异步任务的调度工具。它是Python写的库房,但是它们实现的报道协议为得以应用ruby,php,javascript等调用。异步任务除了消息队列的后台执行之艺术,还是一样种则是跟进时间的计划任务。下面用会见介绍如何行使celery实现就片种需求。

Celry broker 和 backend

顶早学习celery的时段,冒出了一个rabbitmq,又冒充出一个redis。当时一头雾水。实际上这多亏celery的计划奥妙。简单的话,rabbitmq是一个用Erlang写的精锐的音信队列工具。在celery中可以扮演broker的角色。那么什么是broker?

broker是一个信息传的中游件,可以知晓为一个邮箱。每当应用程序调用celery的异步任务的当儿,会朝着broker传递消息,而后celery的worker将会收获到消息,进行对的程序执行。好吧,这个邮箱可以视作是一个信队列。那么什么又是backend,通常程序发送的信,发完就得了了,可能都未知底对方时刻接受了。为这个,celery实现了一个backend,用于存储这些信以及celery执行的组成部分音和结果。对于
brokers,官方推荐是rabbitmq和redis,至于backend,就是数据库啦。为了简单起见,我们且用redis。

Getting Starting

采取celery包含三个方面,其一是概念任务函数,其二是运作celery服务,最后是客户应用程序的调用。

创建一个文本 tasks.py

输入下列代码:

from celery import Celery

brokers = '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

下面就开行celery服务

当当前令行终端运行:

celery -A tasks worker  --loglevel=info

这会儿会看见一对输出。包括注册之任务啦。

下客户端程序如何调用呢?打开一个命执行,进入Python环境

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

以celery命令行可瞥见celery执行之日记:

[2015-09-20 21:37:06,086: INFO/MainProcess] Task proj.tasks.add[76beb980-0f55-4629-a4fb-4a1776428ea8] succeeded in 0.00089102005586s: 6

开拓 backend的redis,也堪望见celery执行之音。

兹经常在python环境被调用的add函数,实际上通常以应用程序中调用这个法子。需要小心,如果管返回值赋值给一个变量,那么原来的应用程序也会见吃封堵,需要拭目以待异步任务回到的结果。因此,实际利用中,不欲把结果赋值。

计划任务

上述的运用是简简单单的安排,下面介绍一个再次强健的计来用celery。首先创建一个python包,celery服务,姑且命名吧proj。目录文件如下:

☁  proj  tree
.
├── __init__.py
├── celery.py           # 创建 celery 实例
├── config.py               # 配置文件
└── tasks.py                # 任务函数

首先是 celery.py

#!/usr/bin/env python
# -*- 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()

立无异于次创 app,并没直接指定 broker 和 backend。而是在布局文件中。

config.py

#!/usr/bin/env python
# -*- 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

#!/usr/bin/env python
# -*- 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

如今以任务吗蛮简单,直接在客户端代码调用 proj.tasks 里的函数即可。

Scheduler

一样栽普遍的求是各级隔一段时间执行一个职责。配置如下

config.py

#!/usr/bin/env python
# -*- 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'

CELERY_TIMEZONE = 'Asia/Shanghai'

from datetime import timedelta

CELERYBEAT_SCHEDULE = {
    'add-every-30-seconds': {
         'task': 'proj.tasks.add',
         'schedule': timedelta(seconds=30),
         'args': (16, 16)
    },
}

只顾安排文件要指定时区。这段代码表示每隔30秒执行 add 函数。

若是以了 scheduler, 启动 celery需要丰富-B 参数

celery -A proj worker -B -l info

crontab

计划任务当然为堪用crontab实现,celery也来crontab模式。修改 config.py

#!/usr/bin/env python
# -*- 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'

CELERY_TIMEZONE = 'Asia/Shanghai'

from celery.schedules import crontab

CELERYBEAT_SCHEDULE = {
    # 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),
    },
}

总的说来,scheduler的切分度更仔细,可以准确到秒。crontab模式就是绝不说了。当然celery还有复尖端的用法,比如多单机器使用,启用多单worker并发处理等。