将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 实例。
所以这有点繁琐,任何服务器都很难以一种很好的通用方式做到这一点,因为合适的方式实际上还取决于托管的应用程序及其要求。
问题是您是否真的需要做到这些。无论如何,请求都将不可避免地失败,用户必须处理这个问题,所以通常在重启时中断少数请求并不是什么大问题。应用程序有什么特别之处,您需要设置更高的标准并尝试确保零请求被中断?