异步任务神器 Celery 简明笔记

异步职分

异步任务是web开发中三个很常见的法门。对于有个别耗时耗财富的操作,往往从主应用中隔离,通过异步的措施执行。简单的说,做一个报了名的作用,在用户采用邮箱注册成功将来,要求给该邮筒发送一封激活邮件。若是间接放在应用中,则调用发邮件的进度会遇见网络IO的封堵,比好优雅的办法则是利用异步义务,应用在作业逻辑中触发1个异步职分。

落实异步义务的工具有不少,其原理都以利用二个任务队列,比如动用redis生产消费模型恐怕揭发订阅方式完毕一个简单的信息队列

除却redis,还是可以采纳其它3个神器—Celery。Celery是2个异步职分的调度工具。它是Python写的库,然则它完成的简报协议也得以动用ruby,php,javascript等调用。异步义务除了音信队列的后台执行的法门,依旧一种则是跟进时间的布署义务。上边将会介绍如何利用celery完成那三种必要。

Celry broker 和 backend

最早学习celery的时候,冒出了二个rabbitmq,又冒出一个redis。当时三只雾水。实际上那正是celery的设计奥妙。容易的话,rabbitmq是三个利用Erlang写的精锐的新闻队列工具。在celery中可以扮演broker的角色。那么如何是broker?

broker是2个新闻传输的中间件,可以领略为1个信箱。每当应用程序调用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。首先成立2个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

一种常见的必要是每隔一段时间执行2个职务。配置如下

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并发处理等。