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,就是不论任务错过了多长时间,都会再次执行。

最近公司项目中遇到了个 ApScheduler 不执行的奇葩问题,这个项目有两个环境,一个是外网的开发环境,一个是部署到客户现场的内网环境,最近现场反馈好几个定时任务最近到时间都不会执行,而且很随机,有时候就会执行,有时候又不会执行,和抽风了一样。
       不知你有没有遇到APScheduler定时任务部分未执行的情况,我反正是遇到了,任务随机性的不执行,一看官网文档,才知道是自己的使用方法不对。        当前网上的大多数文章都只说了基本的使用方法,没说注意事项。我在这里整理一下: 1. Executor 是默认大小为10的ThreadPoolExecutor。 from apscheduler.schedulers.background import
最近需要写个日更新的程序,用time.sleep()不能很好的控制任务的执行时间 于是,就使用了python的任务调度模块apscheduler,这个模块功能真的是很强大 具体的就不多讲了 将任务程序都设置好,之后,任务只在第一天执行,后面两天都没有执行 通过仔细检查log之后,发现了异常 正常的本次运行完,下次的任务执行时间log为: 144 - 20...
1. 定义全局变量scheduler import apscheduler.scheduler.background import BackgroundScheduler scheduler = BackgroundScheduler() scheduler.start() 2. 问题 2.1 在定时任务正常执行过程中,如果服务挂掉了,下次再次启动时,前面next_run_time时间点执行的任务不会被执行了,更新next_run_time为当前最新执行的时间 def scheduler_tas
1. 环境与背景,使用Flask 还有flask-apscheduler flask-sqlalchemy 这几个东西重构了一个自己版本的https://github.com/guomaoqiu/JobCenter工具,用来管理自己的工作,因为应用使用了flask-sqlalchemy 所以很多操作要在 flask的app_context中运行,就使用了flask-apscheduler,遇到了Run time of job xxx was missed by xxx...bug 先说结论: fl...
from apscheduler.schedulers.blocking import BlockingScheduler from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR, EVENT_JOB_MISSED import datetime import logging logger = logging.getLogger('job') logging.basicConfig(
在你提供的引用中,第一个引用是关于webpack配置中的一个错误,错误信息是关于CSS loader的重复问题。解决这个问题的方法是去掉重复的loader。 第二个引用是关于material-ui报错的问题,报错信息是"TypeError: require(...) is not a function"。这个错误通常是因为在引入material-ui的时候出现了问题。可能是因为版本不兼容或者引用路径有误。需要检查一下相关的配置和依赖项。 第三个引用是关于模块构建失败的错误,错误信息是"SyntaxError: Unexpected token (5:11)"。这个错误通常是由于代码中缺少分号导致的。在JavaScript中,分号是语句结束的标志,如果缺少分号,就会出现语法错误。需要在相应的位置添加分号来解决这个问题。 至于你提到的"Module build failed (from ./node modules/postcss-loader/src/index.js): SyntaxError Missed semicolon"的问题,根据你提供的信息来看,这是一个语法错误,具体是缺少分号的问题。需要在相应的代码位置添加分号来解决这个问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [React路上遇到的那些问题以及解决方案](https://blog.csdn.net/liangklfang/article/details/53694994)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]