解决方案:APScheduler定时任务不执行,报错Run time of job ... was missed by ...

简介: 解决方案:APScheduler定时任务不执行,报错Run time of job ... was missed by ...


ApScheduler

APScheduler(Advanced Python Scheduler)是一个用于在 Python 应用程序中执行定时任务的库。它提供了一种简单而强大的方式,允许你在指定的时间间隔、日期或特定事件触发时执行任务。

问题背景

最近公司项目中遇到了个 ApScheduler 不执行的奇葩问题,这个项目有两个环境,一个是外网的开发环境,一个是部署到客户现场的内网环境,最近现场反馈好几个定时任务最近到时间都不会执行,而且很随机,有时候就会执行,有时候又不会执行,和抽风了一样。

解决方案

最后定位到是由于现场创建的定时任务太多了(八十多个),APScheduler 默认的调度配置忙不过来了。

最开始的代码写的比较简单,都是基于默认的配置:

...
jobstores = {
    'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
}
back_scheduler = BackgroundScheduler(timezone="Asia/Shanghai", jobstores=jobstores)
...

翻阅官方文档可以看到,BackgroundScheduler 默认的执行器是 10 个容量的线程执行器。注意这个 10!从下面的文档可以看到。

APScheduler Documentation - Configuring the scheduler

定时任务没有执行可能有两个原因:

  1. 定时任务要执行的时间正好发生了停机/重启。这种情况可能性比较小,除非你真的运气不好,恰好赶在了那个时间。
  2. **Executor 如果是默认的 10 个容量的线程池,恰好 10 个线程都在忙,恰好又有一个任务该执行了,由于没有空闲线程来处理,这个任务将被抛弃。**这个问题就比较常见了,也是我遇到问题的罪魁祸首。如果是因为没有线程处理导致的定时任务不执行,那么会输出日志:Run time of job "xxx (trigger: cron[year='*', month='*', day='*', day_of_week='*', hour='*', minute='*', second='*'], next run at: 2024-01-05 11:17:37 CST)" was missed by 0:00:05.255671,抓住关键词:was missed by,那么基本上就是这个问题了。

这两个原因都可以从官网中找到:

APScheduler Documentation - Missed job executions and coalescing

最后修改代码,适当加大线程池大小,并在创建任务的时候加上 misfire_grace_time 参数。

...
jobstores = {
    'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
}
job_defaults = {
    'coalesce': True,
    'misfire_grace_time': None
}
# 加大线程池大小
executors = {
    'default': ThreadPoolExecutor(30)
}
back_scheduler = BackgroundScheduler(timezone="Asia/Shanghai", jobstores=jobstores, job_defaults=job_defaults, executors=executors)
...

也可以在创建任务的时候为每个任务单独指定:

...
# 当任务被唤起时,如果在 misfire_grace_time 时间差内,依然运行。
back_scheduler.add_job(... , misfire_grace_time=30)
...

每个任务都有一个 misfire_grace_time,单位:秒,默认是 0 秒。意思是那些错过的任务在有条件执行时(有线程空闲出来/服务已恢复),如果还没有超过 misfire_grace_time,就会被再次执行。如果 misfire_grace_time=None,就是不论任务错过了多长时间,都会再次执行。



相关文章
|
SQL 数据库 Python
SQLAlchemy中filter函数的使用
SQLAlchemy中filter函数的使用
|
11月前
|
数据采集 调度 数据库
flask-apscheduler的使用与示例
flask-apscheduler的使用与示例
702 4
|
12月前
|
调度 数据库 Python
python中APScheduler的使用详解(python3经典编程案例)
文章详细讲解了在Python中使用APScheduler来安排和执行定时任务的方法,包括不同调度器的配置与使用场景。
524 0
|
调度 Python
Python任务调度神器:APScheduler使用详解
Python任务调度神器:APScheduler使用详解
2449 3
|
Linux 调度 数据库
Django使用django-apscheduler实现定时任务
【7月更文挑战第8天】定时任务可以在后台定时执行指定的代码,避免了很多人为操作。下面是在Django项目中如何使用定时任务的具体操作流程
1038 1
|
存储 Linux 调度
太好用了!Python 定时任务调度框架 APScheduler 详解!
太好用了!Python 定时任务调度框架 APScheduler 详解!
1357 0
|
11月前
|
缓存 JavaScript
Vue 中 computed 与 method 的区别
【10月更文挑战第15天】computed 和 method 是 Vue 中两个重要的选项,它们在功能和特点上存在着明显的区别。理解并合理运用它们的区别,可以帮助我们构建更高效、更具可维护性的 Vue 应用。在实际开发中,要根据具体情况灵活选择使用,以满足不同的需求。
202 2
|
存储 缓存 监控
python任务调度利器-APScheduler
APScheduler是Python的任务调度库,提供基于时间、固定时间点和CRONTAB的任务调度,适用于离线作业和缓存更新等场景。它包含触发器、调度器、任务存储器、执行器和任务事件组件。安装使用`pip install apscheduler`,简单示例展示了如何配置调度器、添加任务并监听任务异常。支持的触发器有间隔、日期和CRON类型,执行器包括线程池和进程池等。任务存储器可选择内存或各种数据库存储。调度器模式有BlockingScheduler和BackgroundScheduler等,可进行任务的添加、删除、暂停和修改,并监听任务事件。5月更文挑战第20天
373 0
|
12月前
|
SQL 关系型数据库 MySQL
SQLAlchemy + 协程,实现异步的 ORM
SQLAlchemy + 协程,实现异步的 ORM
757 1
在 Django 上实现定时任务的指南
在 Django 中实现定时任务有多种方法,包括使用 Celery 和 Celery Beat、django-background-tasks、以及 APScheduler。根据您的需求和应用场景,可以选择最适合的方案。每种方法都有其优缺点,选择时应考虑任务复杂性、系统资源、以及维护成本。通过这些工具,您可以有效地管理和调度后台任务,提高应用程序的自动化水平和运行效率。