Django是python语言下的一个比较热门的Web框架,愈来愈多的企业和开发者使用Django实现本身的Web服务器。在Web服务器开发过程当中,有时候咱们不只仅是要实现Web服务器端和用户端的简单逻辑交互,还要实现一些定时任务。举出如下的例子: html
按期删除或缓存Redis数据库的记录
为了追求更高的数据库访问性能,我把Redis做为MySql数据库的缓存。把常访问的数据放在Redis中,而后定时存储到Mysql中。而且把过时的Redis数据删掉.那么这个时候,就须要定时去完成这个任务。python
生成报表
打个比方,你有一个Web电商服务器,天天用户都在会在上面购物。为了很方便的统计出每一个用户每月的消费金额,你在数据库中设计了一张月统计报表。而后使用定时任务,在每月的1号进行统计,检索数据库,计算出每一个用户上个月的的消费金额,逐个存储到月统计报表中。那么这个生成报表的任务就是定时完成的,也就是前面提到的每月的1号。linux
定时发送消息
再如:当你的网站上用户生日来临,你但愿在他生日那天,给用户的邮箱发送生日快乐的祝福。那么这也是定时任务实现的。nginx
上面这些的例子,都是须要定时任务。在Python中,咱们使用的Celery模块完成这项任务。网络上关于Celery的博文不少,大多博文的逻辑比较混乱,所以就有了这篇博文。但愿读者读完有个清晰的认识,而且很好的实战出来,再也不对celery定时任务有任何的困惑,这是我这篇博文的初衷。web
此篇博文没有介绍Celery的工做原理,诸如Broker,Worker等等。在实战以前,这些概念必需要理解清楚。因为网上已经有不少这样的内容,我在文章结尾处贴出了一些参考文档,方便读者学习。redis
始终明确的是:
Celery是Python的第三方库,它能够用因而任何的Python的项目中,由于咱们始终能够把Celery当作一个独立的模块去操纵其它的模块。所以,咱们能够在Django项目中使用的Celery,但值得注意的是,在Django中使用Celery的方式有两种:sql
方法1: 至关于中Django中加入了一个Celery的任务脚本,为了操纵Django,所以须要额外在Celery中配置Django环境,才能操做Django的数据库。数据库
方法2: 因为使用了djcelery,能够在任务中方便的直接操做Django数据库,并且最终的任务能够在Django的后台数据库中查看和修改相关的任务。
两种方法的选择:
从上面的描述看,方法1比方法2少引入一个djcelery模块,缺点是须要本身配置与Django结合的环境。而方法2,比较方便省心,还能在Django后台管理本身的任务。所以若是你在Django中使用Celery,我强烈推荐方法2。django
此篇博文讲述了使用方法2, 但它们二者本质上是同样的。两种方式我都有实践过, 原先我有打算写关于姊妹篇(关于方法1)的博文,名字都想好了,叫"Django中使用Celery实现定时任务(不用djcelery)"。可是因为后来觉得写了也没人看,就懒得更新了,再加上后来离职等因素又疏远了Django后端,因此姊妹篇的计划就一直搁置了。最初这篇文章发表在CSDN上面,后续收到了一些不错的反馈,这篇博文就再更新了一次。(可是姊妹篇的计划却仍是被我放弃了)。后端
闲聊时间已结束,下面是正文。
首先记得: pip install django-celery
下面展现了一个Django项目的目录结构示例:
注意,上述目录中的tasks.py
文件是我新建的,放在app的目录下,整个Celery任务,我只新建了这一个文件。
为了设置Celery,咱们须要对setting.py文件进行配置,过程以下:
INSTALLED_APPS = (
'django.contrib.admin', 'django.contrib.auth', 'djcelery', #此处是新加入的djcelery 'app', )
上述 INSTALLED_APPS
中我省略了无关的模块,注意加入djcelery
便可。
加入 djcelery 后须要执行,migrate迁移,生成数据表。
我在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。
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默认设置的数据库就很好。
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)
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
的具体用法,celery的官方文档讲解的十分详尽(表格):
http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html
我选的三个任务,是我特地挑选的,很是有表明性。第一个是周期任务,它会每隔一个固定时间周期去执行一次相应的task,好比隔1分钟,隔1小时等; 第二个和第三个都是定时任务,定时在每一个时间点,好比天天的6点,或者定时在每月的1号。
周期任务和定时任务有小小的差异,这也是crontab的强大之处,它同时支持这两种。
每一个任务本质上就是一个函数,在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
中的配置。
登陆到Django后台,能够看到后台数据库中看到有任务的参数,效果图暂略。
而后启动终端,切换到Django项目的根目录下,运行:
python manage.py runserver # 启动web服务 python manage.py celery worker -l info # 启动celery woker
这条命令用于启动worker, worker本质上执行任务的线程,就是一个干苦力的工人。
python manage.py celery beat
-l info
# 启动beat, 执行定时任务.(原博客在此处有错误,已经修改。提示:最新的django-celery匹配celery<4.0,>=3.1.15版本。)python manage.py celery beat
-l infobeat
上面这条任务用于启动beater,它就像一个领导,负责把任务分发给工人。
到直接,这篇博文基本就结束了,因为两次更新的时间间隔比较长,最初的思路都记不清了。固然,你确定有一个重要的疑问,那就是若是任务由于系统重启或者其它缘由崩溃了怎么重启呢?对于linux 系统,supervisor能够托管这两条命令,若是任务没有跑起来,它能够本身重启启动任务,这样,就能保证服务器端的定时任务不会由于一些缘由崩溃掉。
1.更深刻的Celery配置:(http://www.cnblogs.com/ajianbeyourself/p/4950758.html)