转自:http://www.jianshu.com/p/1840035cb510

异步任务

异步任务是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

输入下列代码:

  1. from celery import Celery
  2. brokers = 'redis://127.0.0.1:6379/5'
  3. backend = 'redis://127.0.0.1:6379/6'
  4. app = Celery('tasks', broker=broker, backend=backend)
  5. @app.task
  6. def add(x, y):
  7. return x + y

上述代码导入了celery,然后创建了celery实例app,实力话的过程中,指定了任务名tasks(和文件名一致),传入了broker和backend。然后创建了一个任务函数add

下面就启动celery服务

在当前命令行终端运行:

  1. celery -A tasks worker --loglevel=info

此时会看见一对输出。包括注册的任务啦。

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

  1. In [0]:from tasks import add
  2. In [1]: r = add.delay(2, 2)
  3. In [2]: add.delay(2, 2)
  4. Out[2]: <AsyncResult: 6fdb0629-4beb-4eb7-be47-f22be1395e1d>
  5. In [3]: r = add.delay(3, 3)
  6. In [4]: r.re
  7. r.ready r.result r.revoke
  8. In [4]: r.ready()
  9. Out[4]: True
  10. In [6]: r.result
  11. Out[6]: 6
  12. In [7]: r.get()
  13. Out[7]: 6

在celery命令行可以看见celery执行的日志:

  1. [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。目录文件如下:

  1. proj tree
  2. .
  3. ├── __init__.py
  4. ├── celery.py # 创建 celery 实例
  5. ├── config.py # 配置文件
  6. └── tasks.py # 任务函数

首先是 celery.py

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from __future__ import absolute_import
  4. from celery import Celery
  5. app = Celery('proj', include=['proj.tasks'])
  6. app.config_from_object('proj.config')
  7. if __name__ == '__main__':
  8. app.start()

这一次创建 app,并没有直接指定 broker 和 backend。而是在配置文件中。

config.py

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from __future__ import absolute_import
  4. CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/5'
  5. BROKER_URL = 'redis://127.0.0.1:6379/6'

剩下的就是tasks.py

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from __future__ import absolute_import
  4. from proj.celery import app
  5. @app.task
  6. def add(x, y):
  7. return x + y

使用方法也很简单,在proj的同一级目录执行celery:

  1. celery -A proj worker -l info

现在使用任务也很简单,直接在客户端代码调用 proj.tasks 里的函数即可。

Scheduler

一种常见的需求是每隔一段时间执行一个任务。配置如下

config.py

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from __future__ import absolute_import
  4. CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/5'
  5. BROKER_URL = 'redis://127.0.0.1:6379/6'
  6. CELERY_TIMEZONE = 'Asia/Shanghai'
  7. from datetime import timedelta
  8. CELERYBEAT_SCHEDULE = {
  9. 'add-every-30-seconds': {
  10. 'task': 'proj.tasks.add',
  11. 'schedule': timedelta(seconds=30),
  12. 'args': (16, 16)
  13. },
  14. }

注意配置文件需要指定时区。这段代码表示每隔30秒执行 add 函数。

一旦使用了 scheduler, 启动 celery需要加上-B 参数

  1. celery -A proj worker -B -l info

crontab

计划任务当然也可以用crontab实现,celery也有crontab模式。修改 config.py

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. from __future__ import absolute_import
  4. CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/5'
  5. BROKER_URL = 'redis://127.0.0.1:6379/6'
  6. CELERY_TIMEZONE = 'Asia/Shanghai'
  7. from celery.schedules import crontab
  8. CELERYBEAT_SCHEDULE = {
  9. # Executes every Monday morning at 7:30 A.M
  10. 'add-every-monday-morning': {
  11. 'task': 'tasks.add',
  12. 'schedule': crontab(hour=7, minute=30, day_of_week=1),
  13. 'args': (16, 16),
  14. },
  15. }

总而言之,scheduler的切分度更细,可以精确到秒。crontab模式就不用说了。当然celery还有更高级的用法,比如多个机器使用,启用多个worker并发处理等。

文/人世间(简书作者)
原文链接:http://www.jianshu.com/p/1840035cb510
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

异步任务神器 Celery 简明笔记的更多相关文章

  1. 【python】命令行神器 Click 简明笔记

    全文拷贝自 命令行神器 Click 简明笔记 Click Click 是用 Python 写的一个第三方模块,用于快速创建命令行.我们知道,Python 内置了一个 Argparse 的标准库用于创建 ...

  2. 异步任务神器 Celery-入门

    一.Celery入门介绍 在程序的运行过程中,我们经常会碰到一些耗时耗资源的操作,为了避免它们阻塞主程序的运行,我们经常会采用多线程或异步任务.比如,在 Web 开发中,对新用户的注册,我们通常会给他 ...

  3. 命令行神器 Click 简明笔记

    Click 是用 Python 写的一个第三方模块,用于快速创建命令行.我们知道,Python 内置了一个 Argparse 的标准库用于创建命令行,但使用起来有些繁琐,Click 相比于 Argpa ...

  4. 异步任务神器 和定时任务Celery

    异步任务神器 Celery Celery 在程序的运行过程中,我们经常会碰到一些耗时耗资源的操作,为了避免它们阻塞主程序的运行,我们经常会采用多线程或异步任务.比如,在 Web 开发中,对新用户的注册 ...

  5. [django]python异步神器-celery

    python异步神器celery https://segmentfault.com/a/1190000007780963

  6. celery 学习笔记 01-介绍

    celery 学习笔记 01-介绍 celery 是 python 中的常用的任务队列框架,经常用于异步调用.后台任务等工作.celery 本身以 python 写,但协议可在不同的语言中实现,其它语 ...

  7. Git & Github 一页简明笔记

    由于小组工程需要使用git&github的版本控制来协作,但我对其使用并不熟悉,特此写篇一页的笔记放在手边,备随时查阅. 相信这种一页的简明笔记,对大家也是有帮助的.我的笔记总结自廖雪峰的Gi ...

  8. sc7731 Android 5.1 LCD驱动简明笔记之三

    此篇笔记基于sc7731 - android 5.1,对lcd的gralloc库做一个简明笔记. 第一部分 调用gralloc.sc8830.so所谓的Gralloc模块,它就是一个模块,一个操作ke ...

  9. sc7731 Android 5.1 LCD驱动简明笔记之二

    此篇笔记基于sc7731 - android 5.1,对lcd的framebuffer做一个简明笔记. 一共分为两大部分:第一部分,关于LCD的硬件方面的:第二部分,关于lcd核心处理(framebu ...

随机推荐

  1. 【转】[NOIP2003普及组]麦森数

    来源:http://vivid.name/tech/mason.html 不得不纪念一下这道题,因为我今天一整天的时间都花到这道题上了.因为这道题,我学会了快速幂,学会了高精度乘高精度,学会了静态查错 ...

  2. android 完全退出应用程序(重要)

    android退出应用程序会调用android.os.Process.killProcess(android.os.Process.myPid())或是System.exit(0),这只是针对第一个A ...

  3. System.AccessViolationException,尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

    从事件查看器中发现,IIS不定期崩溃并重启的现象.抓取crash dump文件后,发现能够看到异常,但没有堆栈信息(主要是只会看托管代码的堆栈,非托管的不清楚.),问题表现及dump日志的截图如下: ...

  4. 如何将XSD文件以及引入import的文件生成相应的C#类。

    下将微软的 Sample Code Generator 1.4.2.1 如果链接不可以用,请到google上搜索,并安装. 拷贝要生成的XSD相关文件到安装目录,MS-DOS下进入安装目录. 执行命令 ...

  5. 【Reporting Services 报表开发】— 数据表存储格式修改

    文本框 Format属性:日期:输入d(表示简易日期).2007/5/1 0:00:00   输入d之后 变成 2007/5/1 金额:输入C0(表示货币),系统会根据设定值产生对应的货币符号,至于0 ...

  6. JS使用百度地图API

    尚未整理: <script type="text/javascript"> var map = new BMap.Map("dituContent" ...

  7. 03 在Linux下安装Myeclipse及Tomcat(含下载)

    测试环境: 主机系统:Win 7 虚拟机:VMware workstation 11.1.0 虚拟机OS: centos 6.5 64位 Kernel 2.6.32-431-e16.x86_64 My ...

  8. Flex外包团队—开发工具:Flex4.6新特性介绍

    在今年初,Adobe发布了其第一个支持移动应用程序开发的Flex SDK和Flash Builder版本.Flex 4.5引入了一组移动优化的组件和移动优化的应用程序框架,而Flash Builder ...

  9. html5外包—长年承接html5外包业务:《Sencha Touch权威指南》下载

    <Sencha Touch权威指南>内容简介:如何才能全面而透彻地理解和掌握移动应用开发框架Sencha Touch并开发出令人心动的移动应用?<Sencha Touch权威指南&g ...

  10. nginx按天切割日志

    原文链接:http://www.cnblogs.com/benio/archive/2010/10/13/1849935.html  本文只节选部分内容 Nginx自己没有日志分割的功能,一旦时间过长 ...