APScheduler使用BackgroundScheduler无法删除运行中定时任务问题咨询
问题根因
- 你使用的Flask框架默认调试模式会开启自动重载机制,启动两个独立进程:一个进程负责监听代码变更实现热重载,另一个进程负责处理业务请求。
- 你将
BackgroundScheduler的初始化和启动逻辑写在了模块顶层,两个进程都会执行这段代码,相当于同时启动了两个完全独立的调度器实例,各自都添加了ID为my_job的定时任务。 - 接口调用的删除/重调度操作,只会修改处理当前请求的进程内的调度器实例,另一个进程的调度器完全不受影响,因此对应任务还会持续执行。
解决方案
- 关闭Flask热重载功能
启动服务时添加--no-reload参数,或者在代码中配置启动参数,保证仅启动一个进程,调度器只会存在一个实例:
if __name__ == '__main__': # 关闭use_reloader即可避免双进程问题 app.run(debug=True, use_reloader=False)
- 调整调度器初始化逻辑
把调度器的任务添加、启动逻辑放到仅主进程会执行的代码块中,避免子进程重复创建调度器,同时修正原代码中methods参数的写法错误:
from apscheduler.schedulers.background import BackgroundScheduler from flask import Blueprint, request fatturazione = Blueprint("fatturazione", __name__) def importazione_ordini(): print('Hello') return # 仅声明调度器变量,不在顶层启动 scheduler = BackgroundScheduler() @fatturazione.route('/fatturazione/remove_job', methods=['GET','POST']) def remove_job(): try: print('before remove', scheduler.get_jobs()) scheduler.remove_job('my_job') print('after remove', scheduler.get_jobs()) except Exception as e: print(e) return "操作完成" @fatturazione.route('/fatturazione/reschedule_job', methods=['GET','POST']) def reschedule_job(): interval = request.json['interval'] try: scheduler.reschedule_job('my_job', trigger= 'interval', hours= int(interval['hours']), minutes=int(interval['minutes'])) except Exception as e: print(e) return "操作完成" if __name__ == '__main__': # 仅主进程执行调度器的任务添加、启动逻辑 scheduler.add_job(importazione_ordini,'interval', minutes=5, id='my_job') scheduler.start() app.run(debug=True, use_reloader=False)
- 生产环境多worker部署适配
如果是生产环境使用uWSGI、Gunicorn等多worker部署,需要额外配置APScheduler的持久化任务存储(如SQLAlchemy、Redis作为JobStore),实现多进程间任务状态共享,同时添加分布式锁避免任务重复执行,也可以直接将定时调度服务单独拆分,不和Web服务共用进程。
内容的提问来源于stack exchange,提问作者Gabriele
相关产品推荐
相关产品推荐

