zoukankan      html  css  js  c++  java
  • Django中使用Celery实现定时任务(用djcelery)

    一.引言

    Django是python语言下的一个比较热门的Web框架,越来越多的企业和开发者使用Django实现自己的Web服务器。在Web服务器开发过程中,有时候我们不仅仅是要实现Web服务器端和用户端的简单逻辑交互,还要实现一些定时任务。举出以下的例子:  

    1. 定期删除或缓存Redis数据库的记录 
      为了追求更高的数据库访问性能,我把Redis作为MySql数据库的缓存。把常访问的数据放在Redis中,然后定时存储到Mysql中。并且把过期的Redis数据删掉.那么这个时候,就需要定时去完成这个任务。

    2. 生成报表    
      打个比方,你有一个Web电商服务器,每天用户都在会在上面购物。为了很方便的统计出每个用户每个月的消费金额,你在数据库中设计了一张月统计报表。然后使用定时任务,在每个月的1号进行统计,检索数据库,计算出每个用户上个月的的消费金额,逐个存储到月统计报表中。那么这个生成报表的任务就是定时完成的,也就是前面提到的每个月的1号。

    3. 定时发送消息 
      再如:当你的网站上用户生日来临,你希望在他生日那天,给用户的邮箱发送生日快乐的祝福。那么这也是定时任务实现的。

    上面这些的例子,都是需要定时任务。在Python中,我们使用的Celery模块完成这项任务。网络上关于Celery的博文很多,大多博文的逻辑比较混乱,因此就有了这篇博文。希望读者有个清晰的认识,并且很好的实战出来。

    此篇博文没有介绍Celery的工作原理,诸如Broker,Worker等等。在实战之前,这些概念必须要理解清楚。由于网上已经有很多这样的内容,我在文章结尾处贴出了一些参考文档,方便读者学习。


    二.Celery,Django和Djcelery

    始终明确的是: 
    Celery是Python的第三方库,它可以用于是任何的Python的项目中,因为我们始终可以把Celery看成一个独立的模块去操纵其它的模块。因此,我们也可以在Django项目中使用的Celery,但值得注意的是,在Django中使用Celery的方式有两种:

    1. 仅使用Celery。
    2. 同时使用Celery + djcelery .

    方法1: 相当于中Django中加入了一个Celery的任务脚本,为了操纵Django,因此需要额外在Celery中配置Django环境,才能操作Django的数据库。

    方法2: 由于使用了djcelery,可以在任务中方便的直接操作Django数据库,而且最终的任务可以在Django的后台中查看和修改相关的任务。

    两种方法的选择: 
    从上面的描述看,方法1比方法2少引入一个djcelery模块,缺点是需要自己配置与Django结合的环境。而方法2,比较方便省心,还能在Django后台管理自己的任务。因此如果你在Django中使用Celery,我强烈推荐方法2。

    这两种方法我都写了相应的博文。此篇博文讲述了使用djcelery的方法2,至于不用的djcelery仅仅使用Celery模块的方法1,请参考我的另一篇博文:   
    Django中使用Celery实现定时任务(不使用djcelery)

    但它们本质上是一样的。


    三. Django目录结构

    下面展示了一个Django项目的目录结构示例: 
    - app 
      - admin.py 
      - views.py 
      - urls.py 
      - models.py 
      - tasks.py 
    - pro 
      - settings.py 
      - urls.py 
      - urls.py 
      - models.py 
    - manage.py

    注意,上述目录中的tasks.py文件是我新建的,放在app的目录下,整个Celery任务,我只新建了这一个文件。

    四. 配置setting.py

    为了设置Celery,我们需要对setting.py文件进行配置,过程如下:

    1.加入djcelery

    INSTALLED_APPS = (
        'django.contrib.admin',
        'django.contrib.auth',
        'djcelery', #此处是新加入的djcelery
        'app',
    )

    上述 INSTALLED_APPS中我省略了无关的模块,注意加入djcelery即可。   

     

    2. 设置celery参数

    我在setting.py的文件结尾处,加入了如下的celery参数配置,先贴代码,再解释。

    import djcelery
    djcelery.setup_loader()
    BROKER_URL = 'redis://127.0.0.1:6379/6'
    CELERY_IMPORTS = ('app.tasks', )
    CELERY_TIMEZONE = TIME_ZONE
    CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'
    
    # 下面是定时任务的设置,我一共配置了三个定时任务.
    from celery.schedules import crontab
    CELERYBEAT_SCHEDULE = {
        #定时任务一: 每24小时周期执行任务(del_redis_data)
        u'删除过期的redis数据': {
            "task": "app.tasks.del_redis_data",
            "schedule": crontab(hour='*/24'),
            "args": (),
        },
        #定时任务二: 每天的凌晨12:30分,执行任务(back_up1)
        u'生成日报表': {
            'task': 'app.tasks.back_up1',
            'schedule': crontab(minute=30, hour=0),
            "args": ()
        },
        #定时任务三:每个月的1号的6:00启动,执行任务(back_up2)
        u'生成统计报表': {
                'task': 'app.tasks.back_up2',
                'schedule': crontab(hour=6, minute=0,   day_of_month='1'),
                "args": ()
        },
    }

    上述代码释义:

    当djcelery.setup_loader()运行时,Celery便会去查看INSTALLD_APPS下包含的所有app目录中的tasks.py文件,找到标记为task的方法,将它们注册为celery task。

    1.

    BROKER_URL = 'redis://127.0.0.1:6379/6'

    broker是代理人,它负责分发任务给worker去执行。我使用的是Redis作为broker,当然你也可以用其它的broker,比如官方就比较推荐使用RabbitMQ.

    有的博客中提到要配置关键字:CELERY_RESULT_BACKEND,例如:

    CELERY_RESULT_BACKEND = 'amqp://guest@localhost//' #可以不用写

    我没有配置这个关键字。因为如果没有配置,此时Django会使用默认的数据库(也是你指定的orm数据库),作为它的结果作为它的backend。因此你也可以不用写,使用Django默认设置的数据库就很好。 
    2.

    CELERY_IMPORTS = ('app.tasks', )
    CELERY_TIMEZONE = TIME_ZONE
    CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'

    上面第一句是导入目标任务文件,第二句是设置时区,第三句表示使用了django-celery默认的数据库调度模型,任务执行周期都被存在默认指定的orm数据库中.

    更深入的Celery配置:(http://www.cnblogs.com/ajianbeyourself/p/4950758.html
    3.

    from celery.schedules import crontab
    CELERYBEAT_SCHEDULE = {
        #定时任务一: 每24小时周期执行任务(del_redis_data)
        u'删除过期的redis数据': {
            "task": "app.tasks.del_redis_data",
            "schedule": crontab(hour='*/24'),
            "args": (),
        },

    上面是设置定时的时间配置,关于crontab的用法,官方的文档讲解的十分详尽(文档末尾的表格):

    http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html

    5.Tasks任务

    每个任务本质上就是一个函数,在tasks.py中,写入你想要执行的函数即可。我的tasks.py如下:我写的每个任务又臭又长,因此具体的细节就省略了。

    # coding=utf-8
    from celery import task
    
    @task()
    def del_redis_data():
        # 此处是一个删除redis数据的操作。具体略过
    
    @task()
    def back_up1():
        # 此处是一个备份到日报表的操作。具体略过
    
    @task()
    def back_up2():
        # 此处是一个生成统计报表的操作。具体略过

    如果读者需要自己实现一个定时任务,那么上述的task函数必然要自己去定义,我只提供了参考。我上面的三个任务,分别对应了setting.py文件的CELERYBEAT_SCHEDULE的三个定时配置。

    要记住的是,任务只是一个函数,这个函数什么时候调用,取决你在setting.py中的配置。

    6.启动定时任务

    待续: 
    登录到Django后台,可以看到

    7.推荐文章

    1.更深入的Celery配置:(http://www.cnblogs.com/ajianbeyourself/p/4950758.html)

  • 相关阅读:
    java面试之手写单例模式
    如何解决json返回的乱码
    ssm整合之applicationContext.xml
    ssm整合之springmvc.xml文件
    XML之MyBatis配置(1)
    XML之SpringMVC的基本配置
    使用eclipse出现错误:Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    Cannot find class [com.alibaba.druid.pool.DruidDataSuorce]
    eclipse如何关联Tomcat以及创建jsp实例
    新手如何快速使用Git
  • 原文地址:https://www.cnblogs.com/wumingxiaoyao/p/8521567.html
Copyright © 2011-2022 走看看