django-celery-beat搭建定时任务

一、创建django项目和app

1、安装定时任务第三方包

pip install django-celery-beat # 插件用来动态配置定时任务,一般会配合 django_celery_results 一起使用,所以一起安装 django_celery_results
pip install django_celery_results
pip install eventlet # windows下运行celery 4以后版本,还需额外安装eventlet库

2、创建django项目并创建一个使用定时任务的app

1.1创建django项目并创建app

创建的过程省略,不在这里展开,需要注意的是setting文件注册app的配置如下:

INSTALLED_APPS = [
    ......
    'myapp',  # 刚创建的使用定时任务的app
    'django_celery_beat',  # 插件用来动态配置定时任务,只要进行了第一步pip安装就可以直接注册了
]

1.2 创建定时任务数据库

依次执行: python manage.py makemigrations 和 python manage.py migrate
打开数据库发现,自动创建了一些表如下:
在这里插入图片描述
这些都是定时任务需要的表格,自动创建不需要手动管理
django_celery_beat.models.ClockedSchedule # 特定时刻任务
django_celery_beat.models.CrontabSchedule # 特定时间表任务,例如每周1运行的计划
django_celery_beat.models.IntervalSchedule # 以特定间隔(例如,每5秒)运行的计划。
django_celery_beat.models.PeriodicTask # 此模型定义要运行的单个周期性任务。
django_celery_beat.models.PeriodicTasks # 此模型仅用作索引以跟踪计划何时更改
django_celery_beat.models.SolarSchedule # 定制任务

如果安装注册了django_celery_results 还会有另外三个表:
在这里插入图片描述

2、新建一个celery.py文件

文件的作用是指定django环境、创建Celery app和指定Celery配置文件的启动位置,类似与wsgi.py或asgi.py,因此也建议文件创建位置与wsgi.py或asgi.py同级。
文件内容如下:

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery, platforms

# 设置django环境
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'lc_manage.settings.settings')

# 创建一个Celery app
app = Celery('djangotask')
platforms.C_FORCE_ROOT = True   # 如果配置没有生效需要在启动时设置  export C_FORCE_ROOT="true"

#  使用CELERY_ 作为前缀,在celeryconfig.py中写配置
#  app.config_from_object('lc_manage.celeryconfig', namespace="CELERY")
app.config_from_object('lc_manage.celeryconfig')

# 发现任务文件每个app下的tasks.py
app.autodiscover_tasks()

3、创建配置文件config.py

这个文件里的内容可以写到项目的 settings.py里面,因为上面的celery.py 中可以指定配置文件位置;不过内容比较多,还是建议单独创建一个配置文件celeryconfig.py,可以与celery.py 同级目录,文件内容如下:

from __future__ import absolute_import

# broker 设置 指定中间代理人将任务存到哪里,这里是redis的11号库
CELERY_BROKER_URL = 'redis://:123456@127.0.0.1:6379/11'
# 指定 Backend 储存结果的地方,可以使用django数据库(django-db),也可以使用redis,
# 使用django数据库(django-db),以后运行worker就会保存到数据库中,可以通过ORM进行访问
# CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/1'
CELERY_RESULT_BACKEND = 'django-db'

# 使用django_celery_beat插件用来动态配置任务
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

# 指定时区,默认是 UTC
CELERY_TIMEZONE = 'Asia/Shanghai'

# celery 序列化与反序列化配置
CELERY_TASK_SERIALIZER = 'pickle'
CELERY_RESULT_SERIALIZER = 'pickle'
CELERY_ACCEPT_CONTENT = ['pickle', 'json']
CELERY_TASK_IGNORE_RESULT = True

# 有些情况下可以防止死锁  非常重要!
CELERYD_FORCE_EXECV = True
# 为存储结果设置过期日期,默认1天过期。如果beat开启,Celery每天会自动清除。
# 设为0,存储结果永不过期
# CELERY_RESULT_EXPIRES = xx
# CELERY_TASK_RESULT_EXPIRES = 60*60*24  # 后端存储的任务超过一天时,自动删除数据库中的任务数据,单位秒
CELERY_MAX_TASKS_PER_CHILD = 1000  # 每个worker执行1000次任务后,自动重启worker,防止任务占用太多内存导致内存泄漏
# 禁用所有速度限制,如果网络资源有限,不建议开足马力。
CELERY_DISABLE_RATE_LIMITS = True
# celery beat配置(周期性任务设置)
CELERY_ENABLE_UTC = False

# 官方用来修复CELERY_ENABLE_UTC=False and USE_TZ = False 时时间比较错误的问题;
# 详情见:https://github.com/celery/django-celery-beat/pull/216/files
DJANGO_CELERY_BEAT_TZ_AWARE = False

这里需要注意的是,如果在celery.py中配置指定了confiig配置文件使用CELERY前缀:app.config_from_object(‘lc_manage.celeryconfig’, namespace=“CELERY”),那么celeryconfig.py配置文件的参数都应加:CELERY_,当然你也可以不用第二个参数,namespace=“CELERY"写成app.config_from_object(‘lc_manage.celeryconfig’”), 那么celeryconfig.py中就不需要加CELERY_ 前缀,注意一定要统一!!!否则可能 会报错:

consumer: Cannot connect to amqp://guest:**@127.0.0.1:5672//: [Errno 61] Connection refused.

4、加载celery.py

我们自己创建的celery.py虽然与wsgi.py 或者 asgi.py等同级,但是 不会像他们一样自动加载,需要我们通过本级文件下的__init__.py 把celery.py 加载进来,打开__init__.py文件,添加如下内容:

 from __future__ import absolute_import, unicode_literals
 from .celery import app as celery_app
# 使得django启动时加载celery的app
__all__ = ('celery_app',)

5、创建定时任务执行内容

经过上面的配置,django-celery_beta 会自动去扫描每个app目录下是否有 tasks.py 文件,需要创建定时任务的app下我们可以手动创建tasks.py,定时任务就写在这个文件上:

from __future__ import absolute_import, unicode_literals
from celery import shared_task

@shared_task
def add(x, y):
    print("x + y  =  ", x + y)
    return x + y

@shared_task
def mul(x, y):
    print("x * y  =  ", x * y)
    return x * y

二、定时器创建和定时任务添加

1、时间和周期控制:IntervalSchedule、ClockedSchedule和CrontabSchedule

其他帖子都把上面三个称为定时任务与PeriodicTask放一起结束,但是个人理解以上三个都是定时任务时控制时间和周期执行的控制器,并非创建定时任务,真正创建定时任务的只有PeriodicTask,所以这里个人把这三个称为定时任务的“时间和频率控制器”。
IntervalSchedule 按时间间隔频率执行定时任务的控制器,(例:每间隔1H/1M/…执行一次)
ClockedSchedule 指定某个时刻执行定时任务的控制器, (例:2018年8月8号 8:00这个时刻执行)
CrontabSchedule 指定某个时间执行定时任务的控制器 (例:每年的12月星期一的8:30)
导入这四个模块:

from django_celery_beat.models import CrontabSchedule, PeriodicTask, IntervalSchedule,ClockedSchedule 

1.2 IntervalSchedule 时间间隔控制器

参数:every 间隔数,period 间隔单位

schedule, created = IntervalSchedule.objects.update_or_create(
    every=1,
    period=IntervalSchedule.MINUTES)   # 按分钟间隔执行 

第二个参数可选
IntervalSchedule.DAYS 固定间隔天数
IntervalSchedule.HOURS 固定间隔小时数
IntervalSchedule.MINUTES 固定间隔分钟数
IntervalSchedule.SECONDS 固定间隔秒数
IntervalSchedule.MICROSECONDS 固定间隔微秒
返回值可直接解包,其实只有第一个参数schedule有用,在PeriodicTask创建定时任务时作为时间和周期控制参数传入。解包获得的第二个数据created 可以直接用下划线取代

1.3 ClockedSchedule特定时刻定时器

参数:clocked_time 指定时间

clocked, _ = ClockedSchedule.objects.update_or_create(
    clocked_time =datetime.strptime("2020-08-18 16:58:46","%Y-%m-%d %H:%M:%S"))   # 按指定时间执行 

这里第二个参数直接用下划线取代。特定时刻控制一般时执行一次,适合在view中调用执行一次性计划。

2、周期性任务 CrontabSchedule

参数:
month_of_year # 几月执行
day_of_month # 几号执行
day_of_week # 周几执行
hour # 几点执行
minute # 几分执行
timezone # 时区

crontab, _ = CrontabSchedule.objects.update_or_create(
    minute="00",
    hour="23",   
    day_of_week="*",   # 周几执行
    day_of_month='1',  # 几点执行
    month_of_year='*',    
    timezone=pytz.timezone("Asia/Shanghai"),
)

上面的星号代表不使用,上面的配置即: 每月1日的23点执行一次。如果day_of_month=“*”则代表每天23点执行。

3、动态添加任务 PeriodicTask

参数:
name:任务名
task:指定的任务
interval:时间间隔
crontab:时间控制器
clocked:指定时刻控制器
expires:有效日期
one_off:启用状态(如果为True,调度将只运行该任务一次)
start_time:开始时间
enabled:启用
last_run_at:最后运行时间
total_run_count:运行总次数
date_changed:最后的更改时间
description:描述
args: 传参
**注意:
1、interval、crontab、clocked三选一,不可同时使用。
2、name :任务名,确保其唯一性!!!!
3、task:后面是以字符串形式调用定时任务的具体工作内容函数,即第一项的第5条用@shared_task装饰器创建的方法。
4、enabled:是否启用,这里动态创建的话一般设为true
5、args: 传参(task中指定的任务需要传参时使用),注意需要json序列化 json.dumps(…)
其他参数均为非必填项。
**

PeriodicTask.objects.update_or_create(
    name=working_point_record_id + 'working_time_1',
    defaults={
        "task": "apps.tasks.add",
        "crontab": crontab,
        "enabled": True,
        "args": json.dumps([working_point_record_id])
    },

4、封装方法

一般情况下,可以把IntervalSchedule、ClockedSchedule和CrontabSchedule根据业务需求单独封装一个文件,而PeriodicTask.objects直接在对应view视图中调用即可。

三、启动定时任务beat

定时任务是独立与django项目运行的,django只是定时任务的入口和操作数据库的入口,而这前提是django-celery-beat 已经独立启动,django-celery-beat的启动分两步,一是生产者单独启动(beat),而是工作者单独启动(worker),这里启动顺序需要注意一点,建议先启动worker 再启动beat ,曾经遇到先启动beat有可能beat会启动失败。

1、启动工作者worker

此时仍然需要重新打开一个命令窗口,进入django项目的根目录(manage.py同级目录)下:

# Linux下测试,启动Celery
 Celery -A 【项目名称】worker -l info  
 ​
 # Windows下测试,启动Celery
 Celery -A 【项目名称】worker -l info -P eventlet
 ​
 # 如果Windows下Celery不工作,输入如下命令
 Celery -A 【项目名称】worker -l info --pool=solo

2、启动生产者beat

beat 是一个生产者角色,是单独运行,生产者完全不依赖django,需要与django在一个不同的命令窗口运行,但启动时需要先进入django项目的根目录,即与manage.py在同一目录下:

celery  -A 【项目名称】 beat -l info

四、定时任务创建

这里要划重点了,其实看完上面的已经可以使用了,下面的属于优化选择性理解,看个人理解能力和需求:
**一般情况下,定时器创建和定时任务添加 PeriodicTask会在view视图中创建,但是如果view视图比较频繁,那么每次执行view都创建一个定时任务的话会有无数个,会比较占用内存资源,当然可以在celeryconfig.py设置执行多少次后重启任务,高并发下view会不会导致频繁重启,这里需要根据业务逻辑把@shared_task包裹下的任务处理方法做成批量处理放到单独文件中(不需要在view视图中调用,定时调用批处理,那么就是一个任务批量处理数据而已),在间隔固定时间下执行,单纯语言难以表达清楚,理解的就理解了,不理解的就慢慢体会吧。这里需要画重点的是:如果你理解了单个文件写@shared_task批处理方法,那么你的问题重点就是:我如何启动它呢?难道每次在启动beat后在命令行启动吗?虽然也可以,但是如果项目需要创建的定时任务很多怎么办,不用多,几百行可以了,每次在命令行复制粘贴执行命令 吗?当然不要,其实直接创建一个单独的python文件,然后再根目录下的url中导入即可,因为url在项目启动的时候会自动加载一次,也就相当于启动django项目的时候就自动创建了一次定时任务!
**

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/1546.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Keil MDK6要来了,将嵌入式软件开发水平带到新高度,支持跨平台(2023-03-11)

注:这个是MDK6,不是MDK5 AC6,属于下一代MDK视频版: https://www.bilibili.com/video/BV16s4y157WF Keil MDK6要来了,将嵌入式软件开发水平带到新高度,支持跨平台一年一度的全球顶级嵌入式会展Embedded Wor…

操作系统(1.3)--习题

一、课堂习题 1、一个作业第一 次执行时用了5min ,而第二次执行时用了6min,这说明了操作系统的( )特点。 A、并发性 B、共享性 C、虚拟性 D、不确定性 D 2、在计算机系统中,操作系统是( )。 A、处于裸机之上的第一层软件 B、处于硬件之下的低层软件 C、处于应用软件之上的系统软…

对象的创建以及数组中常见的属性与方法

(一)对象创建的三种方法 1、利用对象字面量创建对象 const obj{ name:小开心 } 2、利用new Object创建对象 const obj1new Object({ name:小开心 }) 3、利用构造函数创建对象 构造函数:是一种特殊的函数,主要用来初始化对象&…

Vector的扩容机制

到需要扩容的时候,Vector会根据需要的大小,创建一个新数组,然后把旧数组的元素复制进新数组。 我们可以看到,扩容后,其实是一个新数组,内部元素的地址已经改变了。所以扩容之后,原先的迭代器会…

【Spring事务】声明式事务 使用详解

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ 声明式事务一、编程式事务二、声明式事务&…

PMSM矢量控制笔记(1.1)——电机的机械结构与运行原理

前言:重新整理以前的知识和文章发现,仍然有许多地方没有学得明白,懵懵懂懂含含糊糊的地方多如牛毛,尤其是到了真正实际写东西或者做项目时,如果不是系统的学习了知识,很容易遇到问题就卡壳,也想…

C语言的灵魂---指针(基础)

C语言灵魂指针1.什么是指针?2.指针的大小3.指针的分类3.1比较常规的指针类型3.2指针的解引用操作3.3野指针野指针的成因:4.指针运算4.1指针加减整数4.2指针-指针1.什么是指针? 这个问题我们通常解释为两种情况: 1.指针本质&#…

Unity学习日记13(画布相关)

目录 创建画布 对画布的目标图片进行射线检测 拉锚点 UI文本框使用 按钮 按钮导航 按钮触发事件 输入框 实现单选框 下拉菜单 多选框选项加图片 创建画布 渲染模式 第一个,保持画布在最前方,画布内的内容显示优先级最高。 第二个,…

GitHub 上有些什么好玩的项目?

前言 各个领域模块的都整理了一下,包含游戏、一些沙雕的工具、实用正经的工具以及一些相关的电商项目,希望他们可以给你学习的路上增加几分的乐趣,我们直接进入正题~ 游戏 1.吃豆人 一款经典的游戏开发案例,包括地图绘制、玩家控…

并发基础之线程池(Thread Pool)

目录前言何为线程池线程池优势创建线程池方式直接实例化ThreadPoolExecutor类JUC Executors 创建线程池线程池挖掘Executors简单介绍ThreadPoolExecutor核心类ThreadPoolExecutor 类构造参数含义线程池运行规则线程设置数量结语前言 相信大家都知道当前的很多系统架构都要求高…

echart图表之highcharts

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、HighCharts是什么?二、使用步骤1.引入库2.前端代码3.展现结果4.后台自动截图总结前言 提示:这里可以添加本文要记录的大概内容&…

linux kernel 5.0 inline hook框架

github:https://github.com/WeiJiLab/kernel-hook-framework 一、项目介绍 Usually we want to hack a kernel function, to insert customized code before or after a certain kernel function been called, or to totally replace a function with new one. How can we…

计算机图形学11:二维观察之多边形的裁剪

作者:非妃是公主 专栏:《计算机图形学》 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 文章目录专栏推荐专栏系列文章序一、多边形的裁剪…

Activity工作流(三):Service服务

3. Service服务 所有的Service都通过流程引擎获得。 3.1 RepositoryService 仓库服务是存储相关的服务,一般用来部署流程文件,获取流程文件(bpmn和图片),查询流程定义信息等操作,是引擎中的一个重要的服务。…

Anaconda配置Python新版本tensorflow库(CPU、GPU通用)的方法

本文介绍在Anaconda环境中,下载并配置Python中机器学习、深度学习常用的新版tensorflow库的方法。 在之前的两篇文章基于Python TensorFlow Estimator的深度学习回归与分类代码——DNNRegressor(https://blog.csdn.net/zhebushibiaoshifu/article/detail…

【C++学习】日积月累——SLT中stack使用详解(1)

一、stack的相关概念 stack是一种容器适配器,专门用在具有后进先出的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作; stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提…

图形视图框架的坐标

图形视图基于笛卡尔坐标系;项目在场景中的位置和几何图形由两组数字表示:X 坐标和 Y 坐标。使用未变换的视图观察场景时,场景上的一个单元由屏幕上的一个像素表示。 图形视图中有三种有效的坐标系: 项目坐标场景坐标视图坐标为了简化实现图形…

opencv仿射变换之获取变换矩阵

大家好,我是csdn的博主:lqj_本人 这是我的个人博客主页: lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…

JavaSe第10次笔记

1.Java中,static不能修饰局部变量。 2.构造代码块:可用于成员变量的赋值,但需要注意的是,构造代码块最先执行(比构造方法先)。 3.静态代码块(可用于静态成员变量赋值):写法如下 static { 静态成员操作; } (比构造…

Python逆向及相关知识

今天第二次看见python字节码的逆向题,然后发现了一个介绍Python逆向的文章,所以把文章里的内容简单整理记录一下。 文章参考:https://www.cnblogs.com/blili/p/11799398.html Python运行原理: 一.什么是Python Python 是一种解…