在Django项目中使用djcelery model api创建和更新定时任务--实际使用版本
来源:互联网 发布:python udp server 编辑:程序博客网 时间:2024/05/17 02:43
环境说明
1. 依赖
python 2.7
django==1.8.16
celery==3.1.25
Django==1.8.16
django-celery==3.1.17
djangorestframework==3.5.3
django-filter==1.0.0
django-crispy-forms
2. 设置
在实际使用中我们使用分离式的设置,即celery的设置和初始化与tasks分开
首先,要设置django中的django.conf,即settings.py
djcelery.setup_loader()# BROKER_URL = 'django://' # 直接使用django做broker生产环境不建议,建议使用redis或者rabbitMQBROKER_URL = 'redis://10.xx.xx.xx:6379/0' # broker使用reids# 允许的格式CELERY_ACCEPT_CONTENT = ['pickle', 'json', 'yaml']# CELERY_TASK_SERIALIZER = 'json'# CELERY_RESULT_SERIALIZER = 'json'# 定时任务CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'CELERY_RESULT_BACKEND = 'redis://10.xx.xx.xx:6379/1'# 不用UTCCELERY_ENABLE_UTC = FalseCELERY_TIMEZONE = 'Asia/Shanghai'# 任务结果的时效时间,默认一天CELERY_TASK_RESULT_EXPIRES = 10# log路径CELERYD_LOG_FILE = BASE_DIR + "/logs/celery/celery.log"# beat log路径CELERYBEAT_LOG_FILE = BASE_DIR + "/logs/celery/beat.log"
以上是我在实际使用时的设置,更多详细设置可以参考:celery文档
创建celery.py文件
在django的项目目录中创建celery.py(与settings.py在同一级目录)
# -*- coding: UTF-8 -*-import osfrom celery import Celery# set the default Django settings module for the 'celery' program.os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'syslog.settings')from django.conf import settings # noqaapp = Celery('xxx')# Using a string here means the worker will not have to# pickle the object when using Windows.app.config_from_object('django.conf:settings')app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
这种设置方法可以让celery自动在所有app中查找tasks文件,比较适合多人多APP同时开发的中大型项目
详情参考:Using Celery with Django
创建实际任务tasks.py
首先,创建一个django的app,然后在app目录下创建tasks.py文件
我们先简单定义一个加法,用以说明后面的例子足够了
from xxx.celery import app@app.taskdef add(x, y): return x + y
创建调用djcelery model api的视图
from djcelery import models as celery_modelsdef _create_task(name, task, task_args, crontab_time): ''' name # 任务名字 task # 执行的任务 "myapp.tasks.add" task_args # 任务参数 {"x":1, "Y":1} crontab_time # 定时任务时间 格式: { 'month_of_year': * # 月份 'day_of_month': * # 日期 'hour': * # 小时 'minute':*/2 # 分钟 } ''' # task任务, created是否定时创建 task, created = celery_models.PeriodicTask.objects.get_or_create(name=name, task=task) # 获取 crontab crontab = celery_models.CrontabSchedule.objects.filter(**crontab_time).first() if crontab is None: # 如果没有就创建,有的话就继续复用之前的crontab crontab = celery_models.CrontabSchedule.objects.create(**crontab_time) task.crontab = crontab # 设置crontab task.enabled = True # 开启task # task.args = [int(x) for x in json.loads(task_args)] # 传入task参数 task.args = [int(x) for x in task_args] # 传入task参数 task.save() return Truedef create(self, request, *args, **kwargs): tasks = ['event_alarm', 'continue_event_alarm', 'condition_alarm'] blog_item_id = request.data['blogitem_id'] event_type = request.data['event_type'] intval = request.data['intval'] name = str(blog_item_id) if event_type == 0: task = '.'.join(['syslogalery.tasks', tasks[int(event_type)]]) elif event_type == 1: task = '.'.join(['syslogalery.tasks', tasks[int(event_type)]]) elif event_type == 2: task = '.'.join(['syslogalery.tasks', tasks[int(event_type)]]) task_args = [blog_item_id, intval] crontab_time = { 'month_of_year': '*', # 月份 'day_of_month': '*', # 日期 'hour': '*', # 小时 'minute': '*/' + str(intval) # 分钟 } if _create_task(name, task, task_args, crontab_time): return JsonResponse({'code': 200, 'msg': 'create success'}) else: return JsonResponse({'code': 400, 'msg': 'failed'})
遇到的问题
在上述开发中,直接使用celery -A xxx worker -l info -B,自定义的定时不起作用,所有任务都是以5s为定时执行,不太明白为什么
原因:见2017.2.24更新
解决方法:
使用以下命令启动:
python2.7 manage.py celery -A syslog worker -B -l info
结论
其实际原理就是更新celery的数据库来达到更新定时任务执行的目的,但该djcelery model api封装了celery中的数据库接口,能够改正直接修改celery数据库定时任务不生效的问题,所以建议使用该数据库API。
————————————————————————————————————————————
2017.2.24 更新
定时不生效问题解决方法
偶然一个机会,再次部署前面写的使用celery定时调度的程序,发现又出现了定时不起作用,全是每个5s执行一次的问题,正好有时间就仔细查google下发现好多人遇到这个问题,并测试了解决方法:
针对UTC的设置:CELERY_ENABLE_UTC = True
celery issues#943: Celerybeat runs periodic tasks every 5 seconds regardless of interval
There’s definitely a bug somewhere in celery.schedules.crontab.remaining_delta() or surrounding it and it is related to timezones. I just have no idea what it is exactly.
The bug does not seem to reproduce when I specify CELERY_ENABLE_UTC=True so there’s might be a workaround for this bug.
Always make timezones aware in the schedule even if UTC is disabled #2666
Fixes #943.
@monax Please verify that this works for you.
In any event, setting CELERY_UTC_ENABLE to true is a good idea if you are using a Django version newer than 1.4.
上述更新后,也可以直接使用celery -A xxx worker -l info -B方式启动了
supervisor 部署celery注意事项
推荐使用/usr/bin/celery -A xxx worker -B –logfile=/opt/logfilter/syslog/logs/celery/celery.log –loglevel=INFO
-l 方式已经不在推荐,在celery 4.x中将禁用-l遇到错误提示且celery没有启动成功:
Running a worker with superuser privileges when the
worker accepts messages serialized with pickle is a very bad idea!
解决方法:要用普通用户启动celery
- 在Django项目中使用djcelery model api创建和更新定时任务--实际使用版本
- Django中使用Celery实现定时任务(用djcelery)
- python:在Django项目中使用Celery实现定时任务--简单版
- django使用celery定时任务,使用redis和supervisor。
- 使用crond和at 在linux中定时执行任务
- 在Mac中使用PyCharm编辑器创建一个django项目
- 如何在Swift中创建和使用Model [ MagicalRecord ]
- 在spring中使用定时任务
- 使用django创建项目
- ssh项目中使用quartz来创建自己的定时任务
- 使用Quartz创建定时任务
- 在scrapy中使用django model来存储数据
- 异步任务利器Celery(二)在django项目中使用Celery
- kylin使用Restful API 创建cube和model
- Spring Boot中使用@Scheduled创建定时任务
- Spring Boot中使用@Scheduled创建定时任务
- Spring Boot中使用@Scheduled创建定时任务
- 项目中遇到创建oracle定时任务
- dex2jar反汇编android的dex/APK文件为jar包命令和方法
- javascript运行机制之执行顺序详解
- 分享一下“流程开发时如何根据发起人的部门来确定某个选人控件的范围”
- SVN服务器搭建和使用(二)
- 有哪些 Android 大牛的 blog 值得推荐?
- 在Django项目中使用djcelery model api创建和更新定时任务--实际使用版本
- JSTL标签库(一)核心标签库
- GCD dispatch_semaphore 信号量
- UEFI 文件类型.efi
- 博客迁移
- 动态的数量改变的时候另一个元素也改变
- 16 - 12 - 29 拓扑排序
- android 竖直的seekbar
- 流程的发起权限如何在数据库中批量添加?