在uwsgi应用程序中启动APScheduler,是否会导致每个工作进程都有一个调度器?

10

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

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

我使用 uwsgi+nginx 来提供此应用程序,并使用多个 worker,这样是否会导致多个调度器实例相互独立?如果是这样,单个作业是否会被触发多次?

在这种情况下,最佳策略是什么,以便只得到一个调度器实例并仍能够从计划的作业内访问应用程序上下文?

这个问题 与使用 gunicorn 而不是 uwsgi 时存在相同的问题,但答案可能类似。

以下是将 "app" 定义为 uwsgi 可调用应用程序对象的代码。

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个回答

5

uWSGI有一个名为mules的功能(参见:http://uwsgi-docs.readthedocs.org/en/latest/Mules.html),您可以使用它们在主节点下启动一个不可通过socket访问的脚本。它被设计用于通过调度程序和信号处理卸载主应用程序上的工作,因此似乎非常适合在uwsgi堆栈中部署调度程序。


1

UWSGI有一个名为uwsgi.worker_id()的函数。如果你在特定的worker条件下启动调度程序,就不会出现多个调度程序实例。


1
我假设 worker_id 是在创建时分配的。我如何事先知道需要使用哪个 id 来限定启动调度程序? - Will
仅为“主”进程返回工作人员ID 0。您想在工人#1中添加作业并启动调度程序。如果这样不起作用,请查看(调试)日志并查看调度程序正在执行的操作。 - Alex Grönholm
无论我是在工作进程#1还是#0中启动调度程序,都不应该有任何特殊之处。我打开了调试模式,但调试器只在重新启动uwsgi服务器时输出信息,几乎看起来像是调度程序线程在运行几秒钟后就停止了。 - Will
是的,--enable-threads在配置中,并且在日志中反映出Python线程已启用。这真的很令人困惑。 - Will
UWSGI文档指出,如果worker_id()返回0,则表示当前进程根本不是工作进程。这就是为什么您应该检查工作进程ID == 1。您是否尝试过?如果没有成功,可以添加您用于初始化Web应用程序和调度程序的代码吗? - Alex Grönholm
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接