当前位置: 首页 > 面试题库 >

确保只有一个工作进程在运行多个工作进程的金字塔web应用程序中启动apscheduler事件

龙华翰
2023-03-14
问题内容

我们有一个使用金字塔制作的网络应用程序,并通过gunicorn + nginx提供服务。它与8个工作线程/进程一起使用

我们需要工作,我们选择了apscheduler。这是我们如何启动它

from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR
from apscheduler.scheduler import Scheduler

rerun_monitor = Scheduler()
rerun_monitor.start()
rerun_monitor.add_interval_job(job_to_be_run,\
            seconds=JOB_INTERVAL)

问题在于,所有使用gunicorn的员工进程都在调度程序。我们尝试实现文件锁,但它似乎还不够好。什么是确保在任何给定时间只有一个辅助进程拾取预定事件而没有其他线程拾取它的最佳方法是JOB_INTERVAL什么?

该解决方案甚至需要与mod_wsgi配合使用,以防我们稍后决定切换到apache2 + modwsgi。它需要与作为服务员的单个流程开发服务器一起使用。

更新
仅使用Django应用程序,我就面临OP描述的相同问题。我最确定的是,如果原始问题添加此细节不会有太大变化。因此,为了获得更多可见性,我还用标记了这个问题django


问题答案:

由于Gunicorn开始用8名工人(在你的例子),这fork了该程序8次进8点的过程。这8个流程是从Master流程派生的,Master流程监视每个流程的状态并具有添加/删除工作人员的能力。

每个进程都会获取你的APScheduler对象的副本,该对象最初是你主流程的APScheduler的精确副本。这导致每个“第n个”工作人员(进程)总共执行“ n”次作业。

解决此问题的方法是使用以下选项来运行gunicorn:

env/bin/gunicorn module_containing_app:app -b 0.0.0.0:8080 --workers 3 --preload

该–preload标志告诉Gunicorn“ 在派生工作进程之前加载应用程序 ”。这样,每个工作人员都“获得了已由Master实例化的应用程序副本,而不是实例化了应用程序本身”。这意味着以下代码在主进程中仅执行一次:

rerun_monitor = Scheduler()
rerun_monitor.start()
rerun_monitor.add_interval_job(job_to_be_run,\
            seconds=JOB_INTERVAL)

此外,我们需要将Jobstore设置为:memory:以外的其他值。这样,尽管每个工作程序都是自己的独立进程,无法与其他7个进程进行通信,但通过使用本地数据库(而不是内存),我们可以保证一个作业库上的CRUD操作的“真点”。

from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore

rerun_monitor = Scheduler(
    jobstores={'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')})
rerun_monitor.start()
rerun_monitor.add_interval_job(job_to_be_run,\
            seconds=JOB_INTERVAL)

最后,由于要执行BackgroundScheduler,我们要使用它start()。当我们调用start()BackgroundScheduler时,将在后台启动一个新线程,该线程负责调度/执行作业。这很重要,因为请记住在步骤(1)中,由于我们的–preload标志,我们start()在Master Gunicorn过程中仅执行一次该功能。根据定义,分叉的进程不会继承其父级的线程,因此每个工作进程都不会运行BackgroundScheduler线程。

from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore

rerun_monitor = BackgroundScheduler(
    jobstores={'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')})
rerun_monitor.start()
rerun_monitor.add_interval_job(job_to_be_run,\
            seconds=JOB_INTERVAL)

所有这些的结果是,每个Gunicorn工人都有一个APScheduler,该APScheduler被欺骗为“ STARTED”状态,但实际上并没有运行,因为它会丢弃其父线程!每个实例还能够更新作业存储数据库,只是不执行任何作业!



 类似资料:
  • 问题内容: 有什么方法可以配置多个工作进程和/或Web进程以在单个Heroku应用程序容器中运行?还是必须将其分解为多个Heroku应用程序? 例如: 问题答案: 所有进程必须具有唯一的名称。 此外,名称 和 无关紧要,没有特殊含义。 唯一带有重要名称的进程是该进程,如Heroku文档中所述: Web进程类型是特殊的,因为它是唯一将从Heroku路由器接收HTTP流量的进程类型。其他过程类型可以任

  • 问题内容: 有没有一种Python方式可以只运行一个程序实例? 我想出的唯一合理的解决方案是尝试将其作为服务器在某个端口上运行,然后尝试将第二个程序绑定到同一端口-失败。但这不是一个好主意,也许有比这更轻巧的东西了吗? (考虑到程序有时可能会失败,例如segfault-因此“锁定文件”之类的东西将无法工作) 问题答案: 以下代码可以完成此工作,它是跨平台的,并且可以在Python 2.4-3.2上

  • 我在Amazon EC2中有多个应用程序实例,每个实例都运行几个工作进程。我希望每个工作进程都订阅一些通知(例如配置更改)。这个通知基本上应该是广播消息,这样一旦发送,每个工作人员都会收到它。 我知道SQS不支持消息广播。通过查看类似的问题/线索,我看到了使用SNS而不是SQS的建议。由于以下原因,我不确定这是否适用于我: 应用程序实例是自动缩放组的一部分,因此可以动态添加和删除它们。在这种情况下

  • 问题内容: 有没有一种Python方式可以只运行一个程序实例? 我想出的唯一合理的解决方案是尝试将其作为服务器在某个端口上运行,然后尝试将第二个程序绑定到同一端口-失败。但这不是一个好主意,也许有比这更轻巧的东西了吗? (考虑到程序有时可能会失败,例如segfault-因此“锁定文件”之类的东西将无法工作) 问题答案: 以下代码可以完成此工作,它是跨平台的,并且可以在Python 2.4-3.2上

  • 完整堆栈应用程序提供了通过某些命令或文件执行来创建新应用程序的工具。 考虑像web2py框架这样的Python应用程序; 整个项目/应用程序是根据MVC框架创建的。 同样,CherryPy允许用户根据需要设置和配置代码的布局。 在本章中,我们将详细了解如何创建CherryPy应用程序并执行它。 文件系统 该应用程序的文件系统显示在以下屏幕截图中 - 以下是我们在文件系统中拥有的各种文件的简要说明

  • 这些天我们一直在尝试安装hadoop集群。有时成功,但大多数时候失败了。我根据官方文件和一些看似高质量的博客进行配置。 我遇到的问题是:所有进程(包括namenode、datanode、nodemanager、resourcemanager)都可以通过命令查看: 但是奴隶们实际上没有工作。我无法在web界面master:8088或master:50070中看到它们 有人说这是重复的namenode