【问题标题】:How to do graceful application shutdown from mod_wsgi如何从 mod_wsgi 优雅地关闭应用程序
【发布时间】:2018-03-11 15:37:45
【问题描述】:

所以我有一个 Flask 应用程序,我一直在 Flask 的内置服务器上运行,并准备将其移至生产环境。此应用程序管理多个子进程。到目前为止,我一直在使用信号处理正常关机。特别是,我使用的一种关闭模式是向烧瓶服务器发送 SIGHUP 导致应用程序将该信号传播给它的子节点(以便他们可以正常关闭),然后让应用程序进程关闭。

在生产中,我们计划使用 mod_wsgi。我读过wsgi applications really shouldn't be handling signals。

所以我的问题是,我应该如何通过这种设置实现以下行为?:

  • 当 apache 收到 SIGTERM 时,它会在终止之前通知 wsgi 守护进程
  • wsgi 守护程序有机会在关闭之前自行进行一些清理

【问题讨论】:

    标签: python apache python-2.7 flask mod-wsgi


    【解决方案1】:

    将SIGTERM 发送到 Apache 父进程,这就是现在发生的情况。

    当 Apache 父进程收到SIGTERM 时,它会依次将SIGTERM 发送给它的所有子工作进程,如果使用守护模式,它也会发送给托管的 mod_wsgi 守护进程。这些子进程将停止接受新请求,并在子进程被强制关闭之前最多有 3 秒的时间来完成现有请求。

    所以SIGTERM 的默认行为是允许一点时间来完成请求,但不允许长时间运行的请求阻止服务器完全关闭。等待子进程关闭的时间是不可配置的,固定为 3 秒。

    代替SIGTERM,您可以发送SIGWINCH 信号。这将导致 Apache 优雅地停止,但这有问题。

    在SIGWINCH 的情况下发生的情况是,Apache 将再次向其子工作进程发送SIGTERM,但不是在 3 秒后强行终止这些进程,而是允许它们至少运行到任何活动请求已完成。

    这样做的一个问题是没有故障保护。如果这些请求永远不会完成,那么我所知道的没有超时会看到子工作进程被强制关闭。因此,您的服务器可能会在关机时挂起。

    第二个问题是 Apache 仍然会在 3 秒后强行终止托管的 mod_wsgi 守护进程,并且没有(或上次没有查看)一种方法来覆盖 Apache 如何管理这些进程,以启用更多托管守护进程的正常关闭。所以优雅的停止信号在使用守护模式时不会改变任何东西。

    最接近优雅停止的是前端路由层,将新流量从 Apache 实例转移。然后通过运行 Apache 的主机中的某种机制触发一个脚本,该脚本将SIGUSR2 发送到 mod_wsgi 守护进程。假设您已将守护进程组上的graceful-timeout 选项设置为适当的故障保护,这将导致如果所有活动请求都完成,守护进程将退出。如果超时到期,那么它将进入其正常的进程关闭序列,即不接受来自 Apache 子工作进程的新请求,并且在shutdown-timeout(默认 5 秒)触发后,如果请求仍未完成,则该进程被强制关闭.

    在这种情况下,它实际上并没有关闭进程,而是导致它们退出,这将导致它们被替换,因为我们没有告诉整个 Apache 停止,而只是告诉 mod_wsgi 守护进程优雅地重启。在这种情况下,除非您监视一组守护进程并知道它们何时全部重新启动,否则您无法清楚地表明它们都已完成,然后可以关闭整个 Apache 实例。

    所以这有点繁琐,任何服务器都很难以一种很好的通用方式做到这一点,因为合适的方式实际上还取决于托管的应用程序及其要求。

    问题是您是否真的需要做到这些。无论如何,请求都将不可避免地失败,用户必须处理这个问题,所以通常在重启时中断少数请求并不是什么大问题。应用程序有什么特别之处,您需要设置更高的标准并尝试确保零请求被中断?

    【讨论】:

    • 感谢您的详细解答!对我们而言,与其说是确保没有请求被中断,不如说是确保应用程序有机会自行清理。特别是,我们的 WSGI 应用程序产生了长期存在的子进程(它们比请求寿命长,但不会比 Apache 寿命长,因为整个 shebang 都在 docker 容器中运行),并且需要对一些持久性资源进行一些清理当他们退出时。现在,我将开始研究其他选项(包括可能消除清理的需要)。
    • 这些额外产生的进程是否需要从处理请求的同一个进程中产生?有一种方法可以使用 mod_wsgi 为您生成和管理单独的进程,当 Apache 关闭时它们会自动接收 SIGTERM。如果它们没有在 3 秒内关闭,它们将被杀死,就像守护进程一样。
    • 是的,它们是使用应用程序请求生成的(有时是关闭的)。
    • 这意味着您必须只使用一个守护进程运行,否则您将需要一些跨进程锁定方案来确保不会启动多个,如果只能是一个。
    • 我们确实拥有的(跨进程锁定方案)(目前还很初级,但我们正在努力)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-09
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多