利用 celery 实现定时任务
celery支持定时任务,设定好任务的执行时间,celery就会定时自动帮你执行, 这个定时任务模块叫celery beat
Celery安装
由于celery 4.0 ,不再支持 Windows,故我们使用celery3.1.26 在windows环境下进行测试
安装:
pip install celery==3.1.26.post2 django-celery==3.2.2 flower==0.9.2
Django中配置
在主项目的配置文件settings.py 中应用注册表INSTALLED_APPS中加入 djcelery
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', 'djcelery', #加入djcelery ]
在settings.py 中配置celery信息
import djcelery
# 当djcelery.setup_loader()运行时,Celery便会去查看INSTALLD_APPS下包含的所有app目录中的tasks.py文件,找到标记为task的方法,将它们注册为celery task。 djcelery.setup_loader()
#broker是代理人,它负责分发任务给worker去执行。此处用的是是Redis作为broker BROKER_URL = 'redis://127.0.0.1:6379/1'
# 导入目标任务文件 CELERY_IMPORTS = ('app01.tasks')
# 设置时区 CELERY_TIMEZONE = 'Asia/Shanghai'
#表示使用了django-celery默认的数据库调度模型,任务执行周期都被存在默认指定的orm数据库中. CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' from celery.schedules import crontab from celery.schedules import timedelta # 下面是定时任务的设置,我一共配置了三个定时任务. from celery.schedules import crontab CELERYBEAT_SCHEDULE = { #定时任务一: 每24小时周期执行任务(test1) u'任务一': { "task": "app01.tasks.test1", "schedule": crontab(hour='*/24'), "args": (), }, #定时任务二: 每天的凌晨12:30分,执行任务(test2) u'任务二': { 'task': 'app01.tasks.test2', 'schedule': crontab(minute=30, hour=0), "args": () }, #定时任务三:每个月的1号的6:00启动,执行任务(test3) u'任务三': { 'task': 'app01.tasks.test3', 'schedule': crontab(hour=6, minute=0, day_of_month='1'), "args": () }, }
创建应用实例
主工程目录添加celery.py, 添加自动检索django工程tasks任务
project/celery.py
#目的是拒绝隐士引入,celery.py和celery冲突。 from __future__ import absolute_import,unicode_literals import os from celery import Celery from django.conf import settings os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings") #创建celery应用 app = Celery('project') #You can pass the object directly here, but using a string is better since then the worker doesn’t have to serialize the object. app.config_from_object('django.conf:settings') #如果在工程的应用中创建了tasks.py模块,那么Celery应用就会自动去检索创建的任务。比如你添加了一个任#务,在django中会实时地检索出来。 app.autodiscover_tasks(lambda :settings.INSTALLED_APPS)
创建任务 tasks
每个任务本质上就是一个函数,在tasks.py中,写入你想要执行的函数即可
from artproject.celery import app @app.task def test1() pass @app.task def test2() pass @app.task def test2() pass
启动定时任务
启动celery beat周期任务命令:
用于启动beater,它就像一个领导,负责把任务分发给工人。
celery -A proj beat
启动Celery Worker来开始监听并执行任务
beat与worker也可以同时启动,但最好只用于测试,适用于只启动一个worker节点的情况:
用于启动worker, worker本质上执行任务的线程,就是一个干苦力的工人。
celery -A proj worker
beat会在当前目录下建立一个文件celerybeat-schedule来记录任务上次运行的时间,所以要保证celery对当前目录有写入的权限,或者指定文件位置:
celery -A proj beat -s /home/celery/var/run/celerybeat-schedule
supervisor管理celery
先在etc/supervisord.d目录下创建一个名为uwsgi_statrt.ini的配置文件
[program:redis] ;指定运行目录 user=root ;执行命令(redis-server redis配置文件路径) command=redis-server /usr/local/etc/redis.conf ; ; ;启动设置 numprocs=1 ;进程数 autostart=true ;当supervisor启动时,程序将会自动启动 autorestart=true ;自动重启 ;停止信号,默认TERM ;;中断:INT (类似于Ctrl+C)(kill -INT pid),退出后会将写文件或日志(推荐) ;;终止:TERM (kill -TERM pid) ;;挂起:HUP (kill -HUP pid),注意与Ctrl+Z/kill -stop pid不同 ;;从容停止:QUIT (kill -QUIT pid) ;stopsignal=INT ; ;停止信号 stopsignal=INT ;输出日志 stdout_logfile=/var/log/supervisor/redis.log stdout_logfile_maxbytes=10MB ;默认最大50M stdout_logfile_backups=10 ;日志文件备份数,默认为10 ;; ;错误日志 redirect_stderr=false ;为true表示禁止监听错误 stderr_logfile=/var/log/supervisor/redis_err.log stderr_logfile_maxbytes=10MB stderr_logfile_backups=10 [program:celery.worker] ;指定运行目录 user=root directory=/home/project/thinking_library ;运行目录下执行命令 command=/home/env/thinking_library/bin/celery -A thinking_library worker --loglevel info --logfile celery_worker.log ; ; ;启动设置 numprocs=1 ;进程数 autostart=true ;当supervisor启动时,程序将会自动启动 autorestart=true ;自动重启 ; ; ;停止信号,默认TERM ; ;中断:INT (类似于Ctrl+C)(kill -INT pid),退出后会将写文件或日志(推荐) ; ;终止:TERM (kill -TERM pid) ; ;挂起:HUP (kill -HUP pid),注意与Ctrl+Z/kill -stop pid不同 ; ;从容停止:QUIT (kill -QUIT pid) stopsignal=INT ;输出日志 stdout_logfile=/var/log/supervisor/celery_worker.log stdout_logfile_maxbytes=10MB ;默认最大50M stdout_logfile_backups=10 ;日志文件备份数,默认为10 ; ; ;错误日志 redirect_stderr=false ;为true表示禁止监听错误 stderr_logfile=/var/log/supervisor/celery_worker_err.log stderr_logfile_maxbytes=10MB stderr_logfile_backups=10 [program:celery.beat] ;指定运行目录 user=root directory=/home/project/thinking_library ;;运行目录下执行命令 command=/home/env/thinking_library/bin/celery -A thinking_library worker --loglevel info --logfile celery_beat.log ; ; ;启动设置 numprocs=1 ;进程数 autostart=true ;当supervisor启动时,程序将会自动启动 autorestart=true ;自动重启 ; ; ;停止信号 stopsignal=INT ;输出日志 stdout_logfile=/var/log/supervisor/celery_beat.log stdout_logfile_maxbytes=10MB ;默认最大50M stdout_logfile_backups=10 ;日志文件备份数,默认为10 ; ; ;错误日志 redirect_stderr=false ;为true表示禁止监听错误 stderr_logfile=/var/log/supervisor/celery_worker_err.log stderr_logfile_maxbytes=10MB stderr_logfile_backups=10
错误提醒:
测试时启动过一次Beat,beat按理说是只能启动一个的但是不服务器都重启过了还是提示已有进程在运行。
ERROR: Pidfile (celerybeat.pid) already exists. Seems we're already running? (pid: 11068)
解决方法:
删除项目下 celertbeat.pid文件即可