原文链接: http://www.weiguda.com/blog/73/

本篇博文主要介绍在开发环境中的celery使用,请勿用于部署服务器.

许多Django应用需要执行异步任务, 以便不耽误http request的执行. 我们也可以选择许多方法来完成异步任务, 使用Celery是一个比较好的选择, 因为Celery

有着大量的社区支持, 能够完美的扩展, 和Django结合的也很好. Celery不仅能在Django中使用, 还能在其他地方被大量的使用. 因此一旦学会使用Celery, 我

们可以很方便的在其他项目中使用它.

1. Celery版本

本篇博文主要针对Celery 3.0.x. 早期版本的Celery可能有细微的差别.

2. Celery介绍

Celery的主要用处是执行异步任务, 可以选择延期或定时执行功能. 为什么需要执行异步任务呢?

第一, 假设用户正发起一个request, 并等待request完成后返回. 在这一request后面的view功能中, 我们可能需要执行一段花费很长时间的程序任务, 这一时间

可能远远大于用户能忍受的范围. 当这一任务并不需要立刻执行时, 我们便可以使用Celery在后台执行, 而不影响用户浏览网页. 当有任务需要访问远程服务器完

成时, 我们往往都无法确定需要花费的时间.

第二则是定期执行某些任务. 比如每小时需要检查一下天气预报, 然后将数据储存到数据库中. 我们可以编写这一任务, 然后让Celery每小时执行一次. 这样我们

的web应用便能获取最新的天气预报信息.

我们这里所讲的任务task, 就是一个Python功能(function). 定期执行一个任务可以被认为是延时执行该功能. 我们可以使用Celery延迟5分钟调用function

task1, 并传入参数(1, 2, 3). 或者我们也可以每天午夜运行该function.

我们偏向于将Celery放入项目中, 便于task访问统一数据库和Django设置.

当task准备运行时, Celery会将其放入列队queue中. queue中储存着可以运行的task的list. 我们可以使用多个queue, 但为了简单, 这里我们只使用一个.

将任务task放入queue就像加入todo list一样. 为了使task运行, 我们还需要在其他线程中运行的苦工worker. worker实时观察着代运行的task, 并逐一运行这

些task. 你可以使用多个worker, 通常他们位于不同服务器上. 同样为了简单起见, 我们这只是用一个worker.

我们稍后会讨论queue, worker和另外一个十分重要的进程, 接下来我们来动动手:

3. 安装Celery

我们可以使用pip在vietualenv中安装:

pip install django-celery

4. Django设置

我们暂时使用django runserver来启动celery. 而Celery代理人(broker), 我们使用Django database broker implementation. 现在我们只需要知道Celery

需要broker, 使用django自身便可以充当broker. (但在部署时, 我们最好使用更稳定和高效的broker, 例如Redis.)

在settings.py中:

    import djcelery
djcelery.setup_loader()
BROKER_URL = 'django://'
...
INSTALLED_APPS = (
...
'djcelery',
'kombu.transport.django',
...
)

第一二项是必须的, 第三项则告诉Celery使用Django项目作为broker.

在INSTALLED_APPS中添加的djcelery是必须的. kombu.transport.django则是基于Django的broker

最后创建Celery所需的数据表, 如果使用South作为数据迁移工具, 则运行:

python manage.py migrate

否则运行: (Django 1.6或Django 1.7都可以)

python manage.py syncdb

5. 创建一个task

正如前面所说的, 一个task就是一个Pyhton function. 但Celery需要知道这一function是task, 因此我们可以使用celery自带的装饰器decorator: @task. 在

django app目录中创建taske.py:

    from celery import task

    @task()
def add(x, y):
return x + y

当settings.py中的djcelery.setup_loader()运行时, Celery便会查看所有INSTALLED_APPS中app目录中的tasks.py文件, 找到标记为task的function, 并

将它们注册为celery task.

将function标注为task并不会妨碍他们的正常执行. 你还是可以像平时那样调用它: z = add(1, 2).

6. 执行task

让我们以一个简单的例子作为开始. 例如我们希望在用户发出request后异步执行该task, 马上返回response, 从而不阻塞该request, 使用户有一个流畅的访问

过程. 那么, 我们可以使用.delay, 例如在在views.py的一个view中:

    from myapp.tasks import add
...
add.delay(2, 2)
...

Celery会将task加入到queue中, 并马上返回. 而在一旁待命的worker看到该task后, 便会按照设定执行它, 并将他从queue中移除. 而worker则会执行以下代

码:

    import myapp.tasks.add

    myapp.tasks.add(2, 2)

7. 关于import

这里需要注意的是, 在impprt task时, 需要保持一致. 因为在执行djcelery.setup_loader()时, task是以INSTALLED_APPS中的app名,

加.tasks.function_name注册的, 如果我们由于python path不同而使用不同的引用方式时(例如在tasks.py中使用from myproject.myapp.tasks import

add形式), Celery将无法得知这是同一task, 因此可能会引起奇怪的bug.

8. 测试

a. 启动worker

正如之前说到的, 我们需要worker来执行task. 以下是在开发环境中的如何启动worker:

首先启动terminal, 如同开发django项目一样, 激活virtualenv, 切换到django项目目录. 然后启动django自带web服务器: python manage.py runserver.

然后启动worker:

    python manage.py celery worker --loglevel=info

此时, worker将会在该terminal中运行, 并显示输出结果.

b. 启动task

打开新的terminal, 激活virtualenv, 并切换到django项目目录:

    $ python manage.py shell
>>> from myapp.tasks import add
>>> add.delay(2, 2)

此时, 你可以在worker窗口中看到worker执行该task:

    [2014-10-07 08:47:08,076: INFO/MainProcess] Got task from broker: myapp.tasks.add[e080e047-b2a2-43a7-af74-d7d9d98b02fc]
[2014-10-07 08:47:08,299: INFO/MainProcess] Task myapp.tasks.add[e080e047-b2a2-43a7-af74-d7d9d98b02fc] succeeded in 0.183349132538s: 4

9. 另一个例子

下面我们来看一个更为真实的例子, 在views.py和tasks.py中:

    # views.py
from myapp.tasks import do_something_with_form_data def view(request):
form = SomeForm(request.POST)
if form.is_valid():
data = form.cleaned_data
# Schedule a task to process the data later
do_something_with_form_data.delay(data)
return render_to_response(...)
# tasks.py @task
def do_something_with_form_data(data):
call_slow_web_service(data['user'], data['text'], ...)

10. 调试

由于Celery的运行需要启动多个部件, 我们可能会漏掉一两个. 所以我们建议:

  • 使用最简单的设置
  • 使用python debug和logging功能显示当前的进程

11. Eager模式

如果在settings.py设置:

CELERY_ALWAYS_EAGER = True

那么Celery便以eager模式运行, 则task便不需要加delay运行:

    # 若启用eager模式, 则以下两行代码相同
    add.delay(2, 2)
add(2, 2)

12. 查看queue

因为我们使用了django作为broker, queue储存在django的数据库中. 这就意味着我们可以通过django admin查看该queue:

    # admin.py
from django.contrib import admin
from kombu.transport.django import models as kombu_models admin.site.register(kombu_models.Message)

13. 检查结果

每次运行异步task后, Celery都会返回AsyncResult对象作为结果. 你可以将其保存, 然后在将来查看该task是否运行成功和返回结果:

    # views.py

    result = add.delay(2, 2)
...
if result.ready():
print "Task has run"
if result.successful():
print "Result was: %s" % result.result
else:
if isinstance(result.result, Exception):
print "Task failed due to raising an exception"
raise result.result
else:
print "Task failed without raising exception"
else:
print "Task has not yet run"

14. 定期任务

还有一种Celery的常用模式便是执行定期任务. 执行定期任务时, Celery会通过celerybeat进程来完成. Celerybeat会保持运行, 一旦到了某一定期任务需要执

行时, Celerybeat便将其加入到queue中. 不像worker进程, Celerybeat只有需要一个即可.

启动Celerybeat:

   python manage.py celery beat

使Celery运行定期任务的方式有很多种, 我们先看第一种, 将定期任务储存在django数据库中. 即使是在django和celery都运行的状态, 这一方式也可以让我们

方便的修改定期任务. 我们只需要设置settings.py中的一项便能开启这一方式:

    # settings.py
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'

然后我们便可以通过django admin的/admin/djcelery/periodictask/添加定期任务了.

  • Name: 这一定期任务的注册名
  • Task (registered): 可以选择所有已经注册的task之一, 例如前面的add function
  • Task (custom): task的全名, 例如myapp.tasks.add, 但最好还是用以上项
  • Enabled: 是否开启这一定期任务
  • Interval: 定期任务的间隔时间, 例如每隔5分钟
  • Crontab: 如果希望task在某一特定时间运行, 则使用Unix中的Crontab代替interval
  • Arguments: 用于传参数到task中
  • Execution Options: 更高级的设置, 在此不详细说明, 请查看celery官方文档

15. 注意

本篇博文中所描述的方法只适用于开发环境, 而不应当应用于部署环境.

如果希望在部署环境中使用, 最重要的便是使用更稳定和可扩展的broker, 而不是使用kombu.transport.django.

Django中如何使用django-celery完成异步任务1(转)的更多相关文章

  1. Django 中CSRF中间件 'django.middleware.csrf.CsrfViewMiddleware',

    1.Django中CSRF中间件的工作原理及form表单提交需要添加{% csrf_token %}防止出现403错误 CSRF # 表示django全局发送post请求均需要字符串验证功能:防止跨站 ...

  2. Celery在Django中的使用介绍

    Celery在Django中的使用介绍 Celery简介 celery是一个简单.灵活且可靠的,处理大量消息的分布式系统,并且提供维护这样一个系统的必须工具. 它是一个专注于实时处理的任务队列,同时也 ...

  3. Django使用Celery进行异步任务

    Celery Celery是一个功能完备即插即用的异步任务队列系统.它适用于异步处理问题,当发送邮件.或者文件上传, 图像处理等等一些比较耗时的操作,我们可将其异步执行,这样用户不需要等待很久,提高用 ...

  4. Django中使用Celery实现定时任务(用djcelery)

    一.引言 Django是python语言下的一个比较热门的Web框架,越来越多的企业和开发者使用Django实现自己的Web服务器.在Web服务器开发过程中,有时候我们不仅仅是要实现Web服务器端和用 ...

  5. DJango中事务的使用

    Django 中事务的使用 Django默认的事务行为 默认情况下,在Django中事务是自动提交的.当我们运行Django内置的模板修改函数时,例如调用model.save()或model.dele ...

  6. Django 中事务的使用

    目录 Django 中事务的使用 Django默认的事务行为 在HTTP请求上加事务 在View中实现事务控制 使用装饰器 使用context manager autocommit() commit_ ...

  7. Django中ORM介绍和字段及其参数

    ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述 ...

  8. Django中ORM介绍

    Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据 ...

  9. Django 中的 cookie 和 session

    一.cookie 由于HTTP协议是无状态的,而服务器端的业务必须是要有状态的.Cookie诞生的最初目的是为了存储web中的状态信息,以方便服务器端使用.比如判断用户是否是第一次访问网站.目前最新的 ...

  10. django中的ORM介绍和字段及字段参数

    Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据 ...

随机推荐

  1. 浅析Java web程序之客户端和服务器端交互原理(转)

    转载自http://www.cnblogs.com/lys_013/archive/2012/05/05/2484561.html 1. 协议 a. TCP/IP整体构架概述 TCP/IP协议并不完全 ...

  2. R语言实战读书笔记(三)图形初阶

    这篇简直是白写了,写到后面发现ggplot明显更好用 3.1 使用图形 attach(mtcars)plot(wt, mpg) #x轴wt,y轴pgabline(lm(mpg ~ wt)) #画线拟合 ...

  3. 【笨嘴拙舌WINDOWS】实践检验之GDI缩放

    SetMapmode(dc,MM_Text); //先继承MM_TEXT的属性 SetMapMode(dc,MM_ANISOTROPIC); SetWindowExtEx(dc,rect.Right, ...

  4. HDU 1838 Chessboard

    dp[i][j]表示以(i,j)为右下角所含棋盘的最大规模, 如果 s[i][j] == s[i-1][j-1] && s[i][j] != s[i-1][j] && ...

  5. Scrum&Kanban在移动开发团队的实践 (二)

    Scrum&Kanban在移动开发团队的实践系列: Scrum&Kanban在移动开发团队的实践 (一) Scrum&Kanban在移动开发团队的实践 (二) 在第一篇分享文章 ...

  6. JavaScript备忘录-逻辑运算符

    关于 || 和 && 运算符 var name=(document.getElementById('txtName') || '') && document.getEl ...

  7. table 锁定表头,出滚动对齐

    前一段时间来了一个汇总的需求,想锁定表头,这个问题在网上找了老半天,实现起来都比较麻烦,经过这几天的摸索终于找到一个简洁的处理方法 下面介绍一下如何处理的: 1.thead 和tbody 放两个tab ...

  8. s:iterator标签的使用

    1.在说明s:iterator标签的使用前,先了解下struts2中的Value Stack. 这里参考了webwork中对Value Stack的描述,由于struts2是在webwork的基础上进 ...

  9. 64 位系统遇到未在本地计算机上注册 Microsoft.Jet.OLEDB.4.0

    本人写的.net程序部署在windowsserver 2003的操作系统上正常,部署到windows server 2008上时候报错“未在本地计算机上注册 Microsoft.Jet.OLEDB.4 ...

  10. Asp.net 身份验证方式?

    [Forms 身份验证] 通过其可将没有通过身份验证的请求重定向到使用 HTTP 客户端重定向的 HTML 窗体的系统.用户提供凭据并提交该窗体.如果应用程序验证该请求,系统就会发出包含凭据或密钥的 ...