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)

  • 相关阅读:
    DC中为什么要用Uniquify?
    hdu 1596 find the safest road
    hdu2112 HDU Today
    hdu 2066 一个人的旅行
    poj 3026 Borg Maze
    poj 1979 Red and Black
    poj 1321 棋盘问题
    hdu 1010 Tempter of the Bone
    hdu 4861 Couple doubi
    codeforces584B Kolya and Tanya
  • 原文地址:https://www.cnblogs.com/wumingxiaoyao/p/8521567.html
Copyright © 2011-2022 走看看