在uwsgi应用中启动APScheduler会为每个worker生成一个调度器吗?

10 投票
2 回答
5102 浏览
提问于 2025-04-18 10:41

我有一个使用Flask框架的应用程序,需要用到APScheduler的调度功能。我的问题是:

我应该在哪里启动调度器实例呢?

我用uwsgi和nginx来运行这个应用,并且有多个工作进程,这样的话我是不是会有多个调度器实例,它们之间互不知晓?如果是这样的话,同一个任务会被触发多次,对吧?

在这种情况下,最好的策略是什么,才能确保只有一个调度器实例,并且在调度的任务中还能访问到应用的上下文呢?

这个问题也有类似的情况,不过是用gunicorn而不是uwsgi,但答案可能会相似。

下面是定义“app”的代码,它是一个uwsgi可调用的应用对象。包含这段代码的文件叫做wsgi.py(虽然这并不重要)。

app = create_app(config=ProductionConfig())

def job_listener(event):
    get_ = "msg from job '%s'" % (event.job)
    logging.info(get_)

# This code below never gets invoked when I check with worker_id() == 1
# The only time it is run is with worker_id() value of 0
app.sched = Scheduler()
app.sched.add_jobstore(ShelveJobStore('/tmp/apsched_%d' % uwsgi.worker_id()), 'file')
app.sched.add_listener(job_listener,
                   events.EVENT_JOB_EXECUTED |
                   events.EVENT_JOB_MISSED |
                   events.EVENT_JOB_ERROR)
app.sched.start()

2 个回答

1

UWSGI 有一个功能叫做 uwsgi.worker_id()。如果你在某个特定的工作进程中有条件地启动调度器,这样就不会出现多个调度器实例了。

5

uWSGI 有一个叫做“mules”的功能(可以查看这个链接: http://uwsgi-docs.readthedocs.org/en/latest/Mules.html)。你可以用它在主进程下启动一个脚本,而这个脚本是不能通过网络连接访问的。这个功能的设计目的是为了把一些工作从主应用中分担出去,主要是用来处理调度和信号,所以它看起来非常适合在 uWSGI 的环境中部署一个调度器。

撰写回答