flask-apscheduler 定时任务持久化存储后,如何重新从数据库中获取

挥剑为谁 2019-06-02 10:42:11
各位大佬,在flask-apscheduler 进行持久化存储后,当flask重启后,如何从mongo中将已存储的定时任务加载到scheduler中?

1、已完成在flask中的config中进行定时任务设置,代码如下

class APSchedulerJobConfig(object):
# 定时任务配置
JOBS = [
# 测试任务
# {
# 'id': 'shop_list',
# 'func': 'app.sched_tasks.add_tasks.task_calls:shop_list',
# 'args': ('shop_list',),
# 'trigger': 'cron',
# 'second': '*/10'
# },
# 生产任务,cron 循环定时任务,每天定时获取参与聚划算商品的数据
{
'id': 'juhuasuan_goods_items_list_cron',
'func': 'app.sched_tasks.add_tasks.task_calls:juhuasuan_goods_items_list',
'args': ('juhuasuan_goods_items_list_cron',),
'trigger': {
'type': 'cron',
'hour': '12', # 每天中午12点启动
# 'minute': '0',
# 'second': '0'
}
},
# 生产任务,interval 循环间隔任务,每隔一段时间,启动聚划算店铺监控任务,获取最新的参与聚划算的商品
{
'id': 'juhuasuan_shop_list_interval',
'func': 'app.sched_tasks.add_tasks.task_calls:juhuasuan_shop_list',
'args': ('juhuasuan_shop_list_interval', ),
'trigger': 'interval',
# 'seconds': 10 # 每隔10秒执行一次
'minutes': 10 # 每隔10分钟执行一次
},
# 生产任务:date 一次性任务,当flask系统启动时,该任务执行一次
# {
# 'id': 'juhuasuan_shop_list_date',
# 'func': 'app.sched_tasks.add_tasks.task_calls:juhuasuan_shop_list',
# 'args': ('juhuasuan_shop_list_date',),
# 'next_run_time': datetime.now() + timedelta(seconds=10)
# },
# 生产任务:date 一次性任务,当flask系统启动时,该任务执行一次
# {
# 'id': 'juhuasuan_goods_items_list_date',
# 'func': 'app.sched_tasks.add_tasks.task_calls:juhuasuan_goods_items_list',
# 'args': ('juhuasuan_goods_items_list_date',),
# 'next_run_time': datetime.now() + timedelta(seconds=10)
# }
]
config = 'mongodb://{}:{}@{}:{}/{}' # 连接数据库信息
config = config.format(
quote_plus(Config.FLASK_DB_MONGO_USER),
quote_plus(Config.FLASK_DB_MONGO_PASSWORD),
Config.FLASK_DB_MONGO_ADDRESS_OA, Config.FLASK_DB_MONGO_PORT, Config.FLASK_DB_MONGO_BI
)
client = MongoClient(config, read_preference=ReadPreference.NEAREST)
SCHEDULER_JOBSTORES = {
'default': MongoDBJobStore(collection='t_bi_sc_apscheduler_jobs', database=Config.FLASK_DB_MONGO_BI, client=client),
'mongo': MongoDBJobStore(collection='t_bi_sc_apscheduler_jobs', database=Config.FLASK_DB_MONGO_BI, client=client)
}
SCHEDULER_EXECUTORS = {
'default': {'type': 'threadpool', 'max_workers': 20}
}
SCHEDULER_JOB_DEFAULTS = {
'coalesce': True,
'max_instances': 3,
'misfire_grace_time': 3600
}
# APScheduler 定时任务开关
SCHEDLER_API_ENABLED = True
# 解决FLASK DEBUG模式定时任务执行两次
WERKZEUG_RUN_MAIN = True


2、flask:app.__init__.py 中进行scheduler注册,因为项目使用的gunicorn+gevent启动worker,所以在注册scheduler时,使用的是锁机制,代码如下:

# 注册定时任务模块 APScheduler,使用锁机制,解决gunicorn创建多个实例
app.config.from_object(APSchedulerJobConfig)
f = open("scheduler.lock", "wb")
try:
fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
scheduler.init_app(app)
scheduler.start()
except:
pass
def unlock():
fcntl.flock(f, fcntl.LOCK_UN)
f.close()
atexit.register(unlock)


3、因为使用的是gunicorn,那么每个worker之间不能获取app的上下文context,所以,在add_tasks中的__init__.py 中创建了scheduler实例,app.__init__.py 中注册的时候,引入add_tasks.__init__.py中创建的实例,这样就解决了上下文的关系,当其他worker需要使用scheduler.add_job 的时候,引入add_tasks.__init__.py 中的scheduler实例即可获取context上下文,代码如下:

from flask import Blueprint

from flask_apscheduler import APScheduler


sched = Blueprint('sched', __name__)

scheduler = APScheduler()


4、scheduler.add_job的使用,代码如下:

# 启动定时任务,一次性任务,修改状态,把任务添加到任务列表中,系统五分钟执行一次任务列表,周期性任务
args = (params['task_id'], record['monitor_shop'])
job = {
'id': params['task_id'],
'func': 'app.sched_tasks.add_tasks.task_calls:juhuasuan_shop_data',
'args': args,
'seconds': 10,
}
next_time = datetime.now() + timedelta(seconds=job['seconds'])
scheduler.add_job(
func=job['func'], id=job['id'], args=job['args'],
next_run_time=next_time, jobstore='mongo', replace_existing=True
)


现在的问题是:当我的MongoDB中的数据库中,如果没有定时任务的信息,那么当flask项目启动时,定时任务就可以正常的启动,如下图所示:



但是当我MongoDB中存在任务信息时,那flask项目重启时,任务就不能启动,详情如下图所示:



如何在项目重启时,让scheduler从MongoDB中获取以前的定时任务,从而执行定时任务,肯定不能每次启动flask项目时,都去手动删除MongoDB中的定时任务数据,请问各位大佬这个问题如何解决。
...全文
1266 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
郭JX 2020-08-01
  • 打赏
  • 举报
回复
引用 4 楼 qq_35646412 的回复:
配置apscheduler的redis持久化就行,几行代码的事,https://blog.csdn.net/weixin_30765577/article/details/96436292可以看一下这个帖子
搞笑吧你,你这个是动态任务,mongo也是没问题的,这个是配置文件配置的任务
郭JX 2020-08-01
  • 打赏
  • 举报
回复
请问解决了吗
qq_35646412 2019-12-10
  • 打赏
  • 举报
回复
配置apscheduler的redis持久化就行,几行代码的事,https://blog.csdn.net/weixin_30765577/article/details/96436292可以看一下这个帖子
qq_35646412 2019-12-10
  • 打赏
  • 举报
回复
解决了没有,没有的话我教你
挥剑为谁 2019-06-03
  • 打赏
  • 举报
回复
别沉啊,暂时来说,解决的方法是,在使用shell脚本启动项目,在shell脚本中先运行一个py文件,将原来的存储任务的数据库清空,再运行gunicorn启动项目。 但这个给人的感觉不是非常nice,而且还有原来的任务都没有,所以还是希望项目启动时,直接从数据库中获取原来的任务

37,743

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • WuKongSecurity@BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧