uwsgi下apscheduler定时任务启动多次的解决办法

admin
2023-11-25 / 0 评论 / 1 阅读 / 正在检测是否收录...

在Web应用的开发中,有时我们需要定时执行一些任务,比如每天早上8点执行一次特定的任务。而在uWSGI这样的应用服务器环境下,我们需要确保任务只在一个进程中运行,避免重复执行。为了实现这一目标,我们可以使用文件锁来同步多个uWSGI worker进程。

使用APScheduler定时任务

首先,我们使用APScheduler库来创建定时任务。在这个示例中,我们定义了一个名为daily_update_task的任务,它将在每天早上8点执行。

from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from flask import Flask

app = Flask(__name__)

def daily_update_task():
    with app.app_context():
        print('daily_update_task starts...')

scheduler = BackgroundScheduler()
scheduler.add_job(daily_update_task, trigger=CronTrigger.from_crontab('1 8 * * *'))

使用文件锁确保单一运行

接下来,我们使用文件锁来确保只有一个uWSGI worker进程可以创建并运行daily_update_task任务。我们通过fcntl模块获取文件锁,然后创建并启动BackgroundScheduler。

import fcntl
import os

def start_scheduler():
    # 获取当前脚本的绝对路径
    script_path = os.path.abspath(__file__)
    # 使用文件锁
    lock_file = open(script_path + '.lock', 'w')
    try:
        # 尝试获取锁,如果获取失败说明已经有其他实例在运行
        fcntl.flock(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
        
        # 创建并启动调度器
        scheduler = BackgroundScheduler()
        scheduler.add_job(daily_update_task, trigger=CronTrigger.from_crontab('1 8 * * *'))
        scheduler.start()
        
        # 阻塞当前进程,保持文件锁
        while True:
            pass
    except IOError:
        # 文件锁已被其他进程获取,说明已经有一个实例在运行
        print("Another instance is already running.")
    finally:
        # 释放文件锁
        lock_file.close()

if __name__ == '__main__':
    start_scheduler()

这样,我们就确保了在uWSGI下只有一个进程创建并运行了定时任务。当其他进程尝试运行时,它们会检测到文件锁已被获取,从而避免了重复执行任务。

总结

在uWSGI环境下,使用文件锁是一种有效的方法来确保定时任务只在一个进程中运行。通过以上代码,我们成功地创建了一个daily_update_task任务,并使用文件锁避免了多个进程重复运行任务的问题。这对于需要定时执行任务的Web应用是一个实用的技术手段。

0

评论 (0)

取消