zoukankan      html  css  js  c++  java
  • Django搭配Celery进行异步/定时任务(一)初步搭建

    转自:http://blog.csdn.net/samed/article/details/50598371

    以下需求场景很常见:

    1. 用户点击页面按钮,请求后台进行一系列耗时非常高的操作,页面没有响应/一直Loading,用户体验非常不好。

    2. 某些数据需要预先处理,每天凌晨的时候进行运算,大约半小时到1小时才能完成。

    3. 进行外部系统的接口数据调用,接口要求在10秒内返回应答报文,但是Django获取数据之后要进行一定的处理,而此处理时间超过3分钟。

    ……

    基于以上场景,就需要对站点进行异步任务 / 定时任务的处理了。

    因为Django接受到请求之后,会阻塞进程,此过程未处理完毕,就无法响应反馈。

    解决方案有很多,这里说说我觉得稍微靠谱的思路:

    1. 先说针对定时任务,这种解决方案比较多,可以将程序书写成 manage common的方式进行,然后使用crontab调用命令即可

        或者使用celery,也采用crontab的方式进行调用。

    2. 异步任务,目前比较靠谱的就是celery了。

    综上,这里就使用celery的方式进行,manage common的方式改天尝试之后再发文。

    python组件:

    1. python2.7

    2. Django1.7.1

    3. celery( amqp-1.4.9 anyjson-0.3.3 billiard-3.3.0.22 celery-3.1.20 )    #使用pip install celery会自定把这些都装上,默认安装符合依赖的最新版。

    4. django-celery-3.1.17    #还是用pip装,这个是用来支持结果写入数据库的。

    步骤:

    备注:以下内容,顶行书写是终端/命令行命令; #表示注释,实际运行请不要加入; python语法高亮均为文件中的内容; >>> 开头表示终端/命令行方式进入python执行的命令。

    1. 新建django project:

    django-admin startproject django_celery

    cd django_celery

    django-admin startapp demoapp

    2. 新建celery配置:(详情看文末的解释)

    django_celery/django_celery/celery.py:

    [python] view plain copy
     
    1. from __future__ import absolute_import  
    2. import os  
    3. from celery import Celery  
    4. from django.conf import settings  
    5.   
    6. # set the default Django settings module for the 'celery' program.  
    7. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_celery.settings')  
    8.   
    9. app = Celery('django_celery')  
    10.   
    11. # Using a string here means the worker will not have to  
    12. # pickle the object when using Windows.  
    13. app.config_from_object('django.conf:settings')  
    14. app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)  
    15.  
    16. @app.task(bind=True)  
    17. def debug_task(self):  
    18.     print('Request: {0!r}'.format(self.request))  



    3. 设置导入celery实例:

    修改django_celery/django_celery/__init__.py:

    [python] view plain copy
     
    1. from __future__ import absolute_import  
    2.   
    3. # This will make sure the app is always imported when  
    4. # Django starts so that shared_task will use this app.  
    5. from .celery import app as celery_app  



    4. 新建demo tasks:

    django_celery/demoapp/tasks.py:

    [python] view plain copy
     
    1. from __future__ import absolute_import  
    2. from celery import shared_task  
    3.  
    4. @shared_task  
    5. def add(x, y):  
    6.     return x + y  
    7.  
    8. @shared_task  
    9. def mul(x, y):  
    10.     return x * y  
    11.  
    12. @shared_task  
    13. def xsum(numbers):  
    14.     return sum(numbers)  



    5. 修改项目配置:

    一、django_celery/django_celery/settings.py:

    1)【可选】屏蔽不需要的app:admin、auth、contenttypes、sessions、messages、staticfiles。

    2)增加app:'demoapp','djcelery','kombu.transport.django', :

    [python] view plain copy
     
    1. INSTALLED_APPS = (  
    2.     # 'django.contrib.admin',  
    3.     # 'django.contrib.auth',  
    4.     # 'django.contrib.contenttypes',  
    5.     # 'django.contrib.sessions',  
    6.     # 'django.contrib.messages',  
    7.     # 'django.contrib.staticfiles',  
    8.     'demoapp',  
    9.     'djcelery',  
    10.     'kombu.transport.django',  
    11. )  

    3)增加 broker 配置: 
    [python] view plain copy
     
    1. BROKER_URL = 'django://localhost:8000//'  

    二、django_celery/django_celery/urls.py:

    1)【可选】既然都去掉了admin了,那么就把admin的相关内容注释掉:

    [python] view plain copy
     
    1. from django.conf.urls import patterns, include, url  
    2. # from django.contrib import admin  
    3.   
    4. urlpatterns = patterns('',  
    5.     # Examples:  
    6.     # url(r'^$', 'django_celery.views.home', name='home'),  
    7.     # url(r'^blog/', include('blog.urls')),  
    8.   
    9.     # url(r'^admin/', include(admin.site.urls)),  
    10. )  

    6. 准备就绪,检查当前目录结构:

    [python] view plain copy
     
    1. django_celery  
    2. │  db.sqlite3  
    3. │  manage.py  
    4. │  manage.pyc  
    5. │  
    6. ├─demoapp  
    7. │  │  admin.py  
    8. │  │  models.py  
    9. │  │  models.pyc  
    10. │  │  tasks.py  
    11. │  │  tasks.pyc  
    12. │  │  tests.py  
    13. │  │  views.py  
    14. │  │  __init__.py  
    15. │  │  __init__.pyc  
    16. │  │  
    17. │  └─migrations  
    18. │          __init__.py  
    19. │          __init__.pyc  
    20. │  
    21. └─django_celery  
    22.         celery.py  
    23.         celery.pyc  
    24.         settings.py  
    25.         settings.pyc  
    26.         urls.py  
    27.         wsgi.py  
    28.         wsgi.pyc  
    29.         __init__.py  
    30.         __init__.pyc  


    执行命令进行测试:

    python manage.py syncdb                      #同步数据库,仅首次运行

    python managepy runserver                    #运行站点,默认端口8000

    【新终端/命令行】

    python manage.py celery worker -l info        #开启celery worker 进程

    【另一个新终端/命令行】

    python manage.py shell

    >>> from demoapp.tasks import *
    >>> dir()
    ['__builtins__', 'absolute_import', 'add', 'mul', 'shared_task', 'xsum']
    >>> mul(5,2)          #可以看到,直接执行命令是没有问题的,直接返回。
    10
    >>> mul.delay(5,2)       #采用delay方式执行,会发送任务到worker
    <AsyncResult: 2922623d-e89b-48c1-a355-bc8d566d10e7>
    >>> add.delay(2,3)
    <AsyncResult: e07aea9b-86da-4d84-89c7-768aca076b53>

    运行结果(在worker终端/命令行中查看):

    [2016-01-27 17:58:56,418: INFO/MainProcess] Received task: demoapp.tasks.mul[2922623d-e89b-48c1-a355-bc8d566d10e7]
    [2016-01-27 17:58:56,437: INFO/MainProcess] Task demoapp.tasks.mul[2922623d-e89b-48c1-a355-bc8d566d10e7] succeeded in 0.0169999599457s: 10
    [2016-01-27 18:00:46,618: INFO/MainProcess] Received task: demoapp.tasks.add[e07aea9b-86da-4d84-89c7-768aca076b53]
    [2016-01-27 18:00:46,630: INFO/MainProcess] Task demoapp.tasks.add[e07aea9b-86da-4d84-89c7-768aca076b53] succeeded in 0.0100002288818s: 5

    至此,demo结束。

    【此部分内容仅研究使用,时间较忙无需关心】

    1. 下面讲解一下celery.py文件的配置内容,为何要这么配置。

    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_celery.settings')

    设置这个环境变量是为了让 celery 命令能找到 Django 项目。这条语句必须出现在 Celery 实例创建之前。

    app = Celery('django_celery')

    这个 app 就是 Celery 实例。可以有很多 Celery 实例,但是当使用 Django 时,似乎没有必要。

    app.config_from_object('django.conf:settings')

    可以将 settings 对象作为参数传入,但是更好的方式是使用字符串,因为当使用 Windows 系统或者 execv 时 celery worker 不需要序列化 settings 对象。

    app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

    为了重用 Django APP,通常是在单独的 tasks.py 模块中定义所有任务。Celery 会自动发现这些模块,加上这一句后,Celery 会自动发现 Django APP 中定义的任务,前提是遵循如下 tasks.py 约定:

    - app1/
        - tasks.py
        - models.py
    - app2/
        - tasks.py
        - models.py

    2. 关于broker:

    这个是个什么东西,我还是不太理解,按照seeting的配置来说,我理解就是承载的站点。

    BROKER_URL = 'django://localhost:8000//'

    这里要注意我是使用了django自带的broker来作为celery broker,传说可以选的broker有:

    RabbitMQ
    Redis
    database

    更多的内容可以参看参考文献2。

    --------------------------------------

    参考文献:

    1. Celery 3.1 中文文档:Django

    2. First Steps with Celery

  • 相关阅读:
    Maven工程读取properties文件过程
    Nginx实现高可用(了解)
    使用Nginx实现负载均衡(tomcat集群之后实现交叉访问)
    使用Nginx实现反向代理过程(一台服务器部署两个网站)
    一台服务器,通过不同域名区分不同主机,配置步骤
    EditPlus5.0破解激活
    [通知] 博客停更
    [论文理解] 活体检测算法论文小结 (一)
    [CUDA] CUDA编程入门
    [学习笔记]《机器学习基础》 课程总结(一)
  • 原文地址:https://www.cnblogs.com/eternal1025/p/8553869.html
Copyright © 2011-2022 走看看