APScheduler关于Execution of job maximum number of running instances and Run time of job was missed

前言:

因为自用的定时任务出现一些问题,打算周末抽个时间将APScheduler模块弄明白,做个记录,避免再次出现问题。

原因

出现这两个错误的原因实在定时在调度的时候出现的问题导致的。先给出模块的默认几个参数:

executors = {
	# 执行器的线程与进程数
    'default': ThreadPoolExecutor(10),
    'processpool': ProcessPoolExecutor(10)
}
job_defaults = {
	# 最近多久时间内允许存在的任务数
    'misfire_grace_time': 1,
    # 该定时任务允许最大的实例个数
    'max_instances': 1,
    # 是否运行一次最新的任务,当多个任务堆积时
    'coalesce': True,
    # 默认值的设置很科学啊
}

scheduler = BackgroundScheduler(executors=executors, job_defaults=job_defaults)

Execution of job maximum number of running instances原因

报错信息很明显,达到了运行实例的最大值。由于默认值max_instances的设置,一个时刻只应该运行一个实例,想一下它的合理性,常规情况下定时任务就是应该在下次调度时运行完成。造成这个问题就是设置的定时任务不是很合理。

Run time of job was missed原因

同理,当检测到当前时间减定时执行时的时间大于misfire_grace_time设置的时间时,该任务就会丢失。

临时解决方案(看起来很美)

错误1:

增大max_instances,增大ThreadPoolExecutor:仅仅增大实例个数不够的,没有线程运行程序,积攒到一定时候还是会报错的。再过分一点就是增大misfire_grace_time,让任务堆积着。

错误2:

在1的基础上,修改coalesce为False,这样任务就会一直在调度器堆积着。
看到这,报错已经基本解决了。要是不想知道原理的就可以关闭窗口了。

下面就是介绍一些定时调度原理和彻底解决的问题的方法。

APScheduler介绍

首先介绍4个重要概念:

  • 触发器(triggers)
  • 作业存储器(job stores)
  • 执行器(executors)
  • 调度器(schedulers)

触发器作用是用来决定下次执行任务的时间。触发器在初始配置之后,是一种无状态的(无状态指的什么)。
作业存储器用来存储定时任务,可以存储在内存或者数据库中。作业存储器不能在调度器之间共享(不理解)。
执行器是将具体的任务交给谁去执行,某个进程或线程。当执行完后,会通知调度器。
调度器为开发人员直接设置,用来调用其它3个工具完成定时任务的执行。
一定要了解这四个概念,至少整个调度任务应用层面的东西都可以通过他们之间的关系解决。
四者之间的关系图,辅助记忆:
在这里插入图片描述

APScheduler例子

首先介绍例子运行的环境:

模块版本
Ubuntu18.04
APScheduler3.6.3
Django3.1.3

偷懒程序直接运行在Django框架,可以脚本直接运行。
基础参数配置:
将线程和进程都调为1,容易出现报错,

参数数值
ThreadPoolExecutor1
ProcessPoolExecutor1
misfire_grace_time2(用于区分比较大小,默认为1)
max_instances1
coalesceTrue
两个定时任务:red在打印当前时间后sleep10秒,green在打印当前时间后sleep4秒。
定时任务每3秒调度一次。

任务正常执行如下图所示
在这里插入图片描述
补充说明:在程序运行之初,仅仅调度器开始工作,job并没有运行。图中的00:00为定时任务运行起始点,并不是程序运行起始点。

在只有一个线程的情况下

默认参数
参数数值
misfire_grace_time1
max_instances1
coalesceTrue

运行结果如下:
在这里插入图片描述
因为只有一个线程,所以同一时刻只有一个job可以被调度运行,job stores是以队列的方式进行存储。

  • 00:00
    调度器调度执行器开始工作,生成两个job,apple_red和apple_green,由于只有一个线程,只能够执行red工作,
  • 00:03
    触发器触发判断条件,apple_red有1个job正在执行so大于max_instances,所以跳过执行,apple_green有一个job等待执行,所以跳过。00:06,00:09同理
  • 00:10
    这时apple_red运行完,通知传递给调度器后调度器调度apple_green实例,结果,判断任务持续时间10大于misfire_grace_time,就取消了该job的运行,造成missed。
  • 00:12
    情况等同于00:00。
调整参数
misfire_grace_time:11,max_instances: 1
参数数值
misfire_grace_time11
max_instances1
coalesceTrue

运行结果如下:
在这里插入图片描述
运行实例如下:有颜色代表线程运行,无颜色代表队列状
在这里插入图片描述

因为只有一个线程,所以同一时刻只有一个job可以被调度运行。

  • 00:00
    调度器调度执行器开始工作,生成两个job,apple_red和apple_green,由于只有一个线程,只能够执行red工作,
  • 00:03
    触发器触发判断条件,apple_red有1个job正在执行so大于max_instances,所以跳过执行,apple_green有一个job等待执行,所以跳过。00:06,00:09同理
  • 00:10
    这时apple_red运行完,通知传递给调度器后调度器调度apple_green实例,结果,判断任务持续时间10小于misfire_grace_time11,green运行,job stores为空。
  • 00:12
    情况与00:03相反。
参数调整
misfire_grace_time:1,max_instances: 2
参数数值
misfire_grace_time1
max_instances2
coalesceTrue

运行情况:
在这里插入图片描述

  • 00:00
    同前一种情况,调度器调度执行器开始工作,生成两个job,apple_red和apple_green,由于只有一个线程,只能够执行apple_red工作
  • 00:03
    触发器触发判断条件,生成两个job,red和green,apple_red。
  • 00:06
    apple_red有1个job正在执行和等待的3秒时候生成的job,大于max_instances,所以跳过执行,apple_green有2个job等待执行,所以跳过。00:09同理
  • 00:10
    这时apple_red运行完,通知传递给调度器后,调度器有3job等待,结果,判断任务持续时间10大于misfire_grace_time,就取消了该job的运行,造成missed。
  • 00:12
    同00:00情况。
参数调整
misfire_grace_time:11,max_instances: 2
参数数值
misfire_grace_time11
max_instances2
coalesceTrue

这种情况运行情况理解了一样的,同前一样,只放结果了
运行结果情况:
在这里插入图片描述

两个线程的情况下

参数
参数数值
misfire_grace_time11
max_instances2
coalesceTrue

执行结果如下:
在这里插入图片描述
详细运行过程如下:
在这里插入图片描述

  • 00:00
    同前一种情况,调度器调度执行器开始工作,生成两个job,apple_red和apple_green,两个线程分别执行。
  • 00:03
    触发器触发判断条件,生成两个job,red和green,入队。
  • 00:04
    apple_green完成,执行器返回信号给调度器,调度器从队列中拿出red交给executors执行,
  • 00:06-00:09
    red达到2个,入队一个green。
  • 00:10
    apple_red完成,执行器返回信号给调度器,调度器从队列中拿出green交给executors执行
  • 00:12
    red入队。

总结:

花费了将近一天的时间总算是写完了,文章中有些表述不是很恰当的地方,待完成源码的查看后进行修改,定时任务看似很简单,里面涉及到的细小知识点还是很多的。
参考:
1、官方文档
2、https://cloud.tencent.com/developer/article/1662162
3、http://www.vuln.cn/9121

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值