如何从mod_wsgi执行优雅的应用程序关闭

时间:2017-09-29 17:08:20

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

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

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

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

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

1 个答案:

答案 0 :(得分: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的主机内触发一个脚本,该脚本向mod_wsgi守护进程发送SIGUSR2。假设您已将守护进程组上的graceful-timeout选项设置为足够的故障保护,这将导致守护程序进程在所有活动请求完成时退出。如果超时到期,那么它将进入正常的进程关闭序列,不接受来自Apache子进程进程的新请求,并且在shutdown-timeout(默认5秒)触发后,如果请求仍未完成,则进程为强行关机。

在这种情况下,它实际上并没有关闭进程,而是导致它们退出,这将导致它们被替换,因为我们没有告诉整个Apache停止,只是告诉mod_wsgi守护进程到做一个优雅的重启。在这种情况下,除非您监视一组守护程序进程并知道它们何时重新启动,否则您没有明确指示它们已完成所有操作,然后可以关闭整个Apache实例。

所以它有点繁琐,任何服务器都很难以一种很好的通用方式执行此操作,因为适当的还取决于托管应用程序及其要求。

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

相关问题