背景

业务需求:用户可创建多个多人任务,需要在任务截止时间前一天提醒所有参与者

技术选型:

Celery:分布式任务队列。实现异步与定时

django-celery-beat:实现动态添加定时任务,即在创建多人任务时添加定时。django-celery-beat插件本质上是对数据库表变化检查,一旦有数据库表改变,调度器重新读取任务进行调度

安装与配置

安装

  1. pip install celery
  2. pip install django-celery-beat

配置

  1. INSTALLED_APPS = (
  2. ...,
  3. 'django_celery_beat',
  4. )
  5. # settings.py
  6. TIME_ZONE = 'Asia/Shanghai'
  7. USE_TZ = False
  8. # =================Celery 配置=================
  9. # 使用redis作为broker
  10. REDIS_HOST = 'redis://127.0.0.1:6379/0'
  11. # 关闭 UTC
  12. CELERY_ENABLE_UTC = False
  13. # 设置 django-celery-beat 真正使用的时区
  14. CELERY_TIMEZONE = TIME_ZONE
  15. # 使用 timezone naive 模式,不存储时区信息,只存储经过时区转换后的时间
  16. DJANGO_CELERY_BEAT_TZ_AWARE = False
  17. # 配置 celery 定时任务使用的调度器,使用django_celery_beat插件用来动态配置任务
  18. CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

创建django-celery-beat所需要的数据表

  1. python manage.py migrate

创建celery实例,并定义任务

  1. # 由于django_celery_beat用到了Django的ORM,因此首先需要setup django,否则会报错
  2. import os
  3. import django
  4. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "qaboard.settings")
  5. django.setup()
  6. from celery import Celery
  7. from project import settings
  8. from utils.send_msg import send_msg
  9. # 使用redis作为消息队列,backend也默认为broker使用的队列服务
  10. app = Celery('test', broker=settings.REDIS_HOST)
  11. # 载入django配置文件中以 CELERY 开头的配置
  12. app.config_from_object('project.settings', namespace='CELERY')
  13. @app.task
  14. def test_task():
  15. send_msg("test celery")

启动celery worker和celery beat

  1. celery -A project_celery worker --pool=solo -l info -f logs/celery.log

'-A' 是一个全局配置,定义了APP的位置

'--pool' 是POOL的配置,默认是prefork(并发),选择solo之后,发送的任务不会被并发执行,在worker执行任务过程中,再次发送给worker的任务会排队,执行完一个再执行另一个。不需要并发时可以选择此模式以节约服务器资源

'-l' 定义了log级别

'-f' 定义日志文件路径

  1. celery -A project_celery beat -l info -f logs/beat.log --pidfile=logs/celerybeat.pid

'--pidfile' 用于定位pidfile,pidfile是一个存储了beat进程的进程id的文件,如果此文件存在且此文件中的进程正在运行中,则不会启动新的beat进程

由于配置中已经声明了调度器,因此这里不需要重新声明,否则需要使用

  1. --scheduler django_celery_beat.schedulers:DatabaseScheduler

声明使用DatabaseScheduler

在linux上可以用-B参数同步启动celery beat

  1. celery -A qaboard_celery worker --pool=solo -l info -f logs/celery.log -B

beat的log会输出到celery.log中

动态添加定时任务

PeriodicTask

此模型定义要运行的单个周期性任务。

  1. 必须为任务指定一种Schedule,即clocked, interval, crontab, solar四个字段必须填写一个,且只能填写一个
  2. name字段给任务命名,它是unique的
  3. task字段指定运行的Celery任务,如“proj.tasks.test_task”
  4. one_off:默认值为False,如果one_off=True,任务被运行一次后enabled字段将被置为False,即任务只会运行一次
  5. args:传递给任务的参数,是一个json字符串,如 ["arg1", "arg2"]
  6. expires:过期时间,过期的任务将不再会被驱动触发

使用ClockedSchedule

会在特定的时间触发任务

  1. def test_clock():
  2. clock = ClockedSchedule.objects.create(clocked_time=datetime.now() + timedelta(seconds=10))
  3. PeriodicTask.objects.create(
  4. name="%s" % str(datetime.now()),
  5. task="project_celery.celery_app.test_task",
  6. clocked=clock,
  7. # 如果使用ClockedSchedule,则one_off必须为True
  8. one_off=True
  9. )

不知道为什么我的任务就是无法通过clock触发,beat.log中有DatabaseScheduler: Schedule changed.的记录,但是到了clock指定的时间任务不会被触发,其他的调度器都是可以正常运行的,如果有知道解决方法的同学可以评论告诉我,感谢

使用IntervalSchedule

以特定间隔运行的Schedule

用IntervalSchedule能够实现与ClockedSchedule同样的功能:计算目标时间与当前时间的时间差,令此时间差作为IntervalSchedule的周期,并且将任务的one_off参数置为True

  1. def time_diff(target_time):
  2. diff = target_time - datetime.now()
  3. return int(diff.total_seconds())
  4. def test_interval():
  5. seconds = time_diff(datetime.strptime("2020-3-19 15:39:00", "%Y-%m-%d %H:%M:%S"))
  6. schedule = IntervalSchedule.objects.create(every=seconds, period=IntervalSchedule.SECONDS)
  7. PeriodicTask.objects.create(
  8. name="%s" % str(datetime.now()),
  9. task="project_celery.celery_app.test_task",
  10. interval=schedule,
  11. one_off=True
  12. )

使用CrontabSchedule

使用CrontabSchedule一定要注意将时区设置为当前地区时区

model参数与crontab表达式的对应关系:

  1. minite, hour, day_of_week, day_of_month, month_of_year

全部默认为"*"

  1. def test_crontab():
  2. # 表示 * * * * * ,即每隔一分钟触发一次
  3. schedule = CrontabSchedule.objects.create(timezone='Asia/Shanghai')
  4. PeriodicTask.objects.create(
  5. name="%s" % str(datetime.now()),
  6. task="project_celery.celery_app.test_task",
  7. crontab=schedule,
  8. one_off=True
  9. )

Celery动态添加定时任务的更多相关文章

  1. Celery 分布式任务队列快速入门 以及在Django中动态添加定时任务

    Celery 分布式任务队列快速入门 以及在Django中动态添加定时任务 转自 金角大王 http://www.cnblogs.com/alex3714/articles/6351797.html ...

  2. Quartz动态添加定时任务执行sql(服务启动添加+手动添加)

    系统用来每天插入视图数据... 一.数据库表设计 1.接口配置表(t_m_db_interface_config) 2.接口日志表(t_m_db_interface_log) 3.前端配置页面 查询页 ...

  3. elastic-job动态添加定时任务

    在elastic-job的使用过程中,我们会遇到动态添加定时任务的时候,但是官网上面并没有对这块内容进行说明.按照我的理解以及官网上面elastic-job的框架图,ej的定时任务其实是存储在zook ...

  4. 动态添加定时任务-quartz定时器

    Quartz动态添加.修改和删除定时任务 在项目中有一个需求,需要灵活配置调度任务时间,刚开始用的Java自带的java.util.Timer类,通过调度一个java.util.TimerTask任务 ...

  5. Spring动态添加定时任务

    Spring动态添加定时任务 一.背景 二.需求和实现思路 1.能够动态的添加一个定时任务. 2.能够取消定时任务的执行. 3.动态的修改任务执行的时间. 4.获取定时任务执行的异常 三.代码实现 四 ...

  6. celery 动态配置定时任务

    How to dynamically add or remove tasks to celerybeat? · Issue #3493 · celery/celery https://github.c ...

  7. Spring+Quartz实现动态添加定时任务

    发布时间:2018-12-03   技术:spring4.0.2+quartz2.2.1   概述 在最近工作中,由于涉及到定时任务特别多,而这些工作又是由下属去完成的,在生成环境中经常会出现业务逻辑 ...

  8. celery 动态定时任务探索

    环境: celery 4.3 flask python 3.7 linux 需求: 动态添加定时任务,且方便维护. 解决思路: 参考django-celery 或是celery源码,将定时任务配置放置 ...

  9. Quartz动态添加,修改,删除任务(暂停,任务状态,恢复,最近触发时间)

    首页 博客 学院 下载 图文课 论坛 APP 问答 商城 VIP会员 活动 招聘 ITeye GitChat 写博客 小程序 消息 登录注册 关闭 quartz_Cron表达式一分钟教程 09-05 ...

随机推荐

  1. 【原创】为什么我的 Kafka 总是连接失败呢?

    提出问题 近日助友 Docker 部署 Kafka 服务,服务日志启动正常,但客户端却无法连接 往日曾踩过此坑,然方法均源于博客,其语焉不详,不知为何不行,亦不知为何行,印象不甚深刻,耗费大量时间 为 ...

  2. Typora[MarkDown编辑器]+(PicGo+Github+JsDelivr)[个人图床] ,开启你的高效创作

    使用Typora搭配Picgo开启你的高效创作 0x00 一切都要从MarkDown说起 富文本语言的弊端 平常我们最常用的写作工具,无非是富文本编辑器中的代表--微软家的Office Word.这种 ...

  3. Yuchuan_Linux_C编程之九目录操作相关函数

    一.整体大纲 二.相关函数 1. getcwd 函数作用:获取当前目录 头文件 #include <unistd.h> 函数原型 char *getcwd(char *buf, size_ ...

  4. npm项目创建初始过程详解

    npm install 就是安装模块,npm run dev  就是执行npm script中的命令.当我们执行npm命令的时候,它到哪里去找,这就要说到每个node项目中都有的核心文件package ...

  5. Markdown使用说明

    # Markdown 使用说明 Markdown 是一种**轻量级标记语言** 使用规则: 1. 标题   2. 列表 3. 引用 4. 图片与链接 5. 粗体与斜体 6.表格 7. 代码框 8. 分 ...

  6. Redis04——五分钟明白Redis的哨兵模式

    和所有的数据库一样,Redis也支持集群化,Redis的集群分为分布式集群和主从集群.大部分公司采取的都是主从集群.所以在本篇文章内,我们将着重介绍Redis的主从集群及哨兵机制. 由于Redis的主 ...

  7. C++ 文件操作 FILE*

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> //编程题:往文件里写入字母表的26个字母. //要求:如果字母对应编码值 是奇数则写 ...

  8. synchronized实现原理及其优化-(自旋锁,偏向锁,轻量锁,重量锁)

    1.synchronized概述: synchronized修饰的方法或代码块相当于并发中的临界区,即在同一时刻jvm只允许一个线程进入执行.synchronized是通过锁机制实现同一时刻只允许一个 ...

  9. Ubuntu 18 安装 cuda 10

    1.把预先下好的cuda放到某个目录,如Download. 2.Crtl + Alt + F3 进入tty,使用tty登录. 关闭用户图形界面,sudo systemctl set-default m ...

  10. 常用的 Git 命令与场景

    Git 分布式版本控制系统 它拥有完整的版本控制功能,能够解决多人协作的问题 将自己的代码同步到 Github 上能够提升开发效率 git 会记录你每一次的版本修改操作 常用的 Git 操作 # 指定 ...