Nginx/PHP FPM 优雅停止(SIGQUIT):没那么优雅 [英] Nginx / PHP FPM graceful stop (SIGQUIT): not so graceful

查看:128
本文介绍了Nginx/PHP FPM 优雅停止(SIGQUIT):没那么优雅的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

运行 nginx 1.9.*/PHP 7.0.*(但在 5.6.* 中的行为也完全相同)

Running nginx 1.9.* / PHP 7.0.* (but exact same behavior in 5.6.* also)

尝试在维护期间正常停止 PHP-FPM/nginx 组合以关闭节点.为此,我将 SIGQUIT 发送到 php-fpm,它应该提供正常关闭.

Attempting to gracefully stop a PHP-FPM / nginx combo for node shutdown during maintenance. To do this, I'm sending the SIGQUIT to php-fpm, which should provide a graceful shutdown.

为了测试这个,我做了一个愚蠢的脚本

To test this, I made a dumb script

<?php sleep(5); echo 'done';

使用以下 curl 在本地测试

Tested locally with the following curl

curl -I x.x.x.x:8080

通常产生输出:

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 12 Apr 2016 04:48:00 GMT
Content-Type: text/html; charset=UTF-8
Connection: close

期望:在任何正在进行的请求中间,当请求正常关闭时,当前请求应该完成,但任何其他请求都应该失败.

Desired: in the middle of any in-flight request, when a graceful shutdown is requested, the current requests should finish, but any additional requests should fail.

不幸的是,当我尝试通过发送 SIGQUIT (http://manpages.ubuntu.com/manpages/precise/man8/php5-fpm.8.html) 到 PHP-FPM 主进程:

Unfortunately, when I try to trigger this behavior, by sending a SIGQUIT (http://manpages.ubuntu.com/manpages/precise/man8/php5-fpm.8.html) to the PHP-FPM master process:

kill -s SIGQUIT $FPMPID

连接立即断开,导致 ngnix 502

The connection immediately drops, resulting in an ngnix 502

HTTP/1.1 502 Bad Gateway
Server: nginx
Date: Tue, 12 Apr 2016 04:48:07 GMT
Content-Type: text/html
Content-Length: 166
Connection: close

有什么建议吗?我很想使系统的这一部分尽可能无缝.谢谢!

Any advice? I would love to make this piece of the system as seamless as possible. Thanks!

推荐答案

在同样的情况下挣扎了一段时间后,我相信我已经找到了神奇的配置设置,可以让子进程在死亡之前完成处理请求.

After struggling with this same situation for a while, I believe I've found the magical config setting to make child processes finish handling requests before dying.

http://php.net/manual/en/install.fpm.configuration.php#process-control-timeout

process_control_timeout

子进程等待主进程响应的时间限制

Time limit for child processes to wait for a reaction on signals from master

基本上,通过将其设置为 10s 之类的内容,子进程将等待那么长时间,同时在退出之前处理现有请求.

Basically, by setting this to something like 10s, the child process will wait that long, while handling existing requests before quitting.

不幸的是,似乎 php-fpm 主进程立即退出,因此,受到代码 这里,我写了一个包装脚本:

Unfortunately, it seems that the php-fpm master process exits immediately, so, inspired by the code here, I wrote a wrapper script:

#!/bin/bash

PHP_FPM_PID='/php-fpm.pid'

wait_for_pid () {
    try=0

    while test $try -lt 35 ; do
        if [ ! -f "$1" ] ; then
            try=''
            break
        fi

        echo -n .
        try=`expr $try + 1`
        sleep 1
    done
}

function clean_up {

    echo "Killing $(cat $PHP_FPM_PID)"

    kill -QUIT `cat $PHP_FPM_PID`
    wait_for_pid $PHP_FPM_PID

    echo "Done!"

    exit 0
}

trap clean_up EXIT

nohup php-fpm --daemonize --pid $PHP_FPM_PID 2>&1 &

while true; do sleep 1; done
# ^ do nothing forever

等待 35 秒或直到该 pid 文件被删除(大概是被其中一个子进程删除?我仍然不清楚如何删除它).

which waits 35 seconds or until that pid file has been removed (presumably by one of the child processes? I'm still unclear on how it's removed).

无论如何,这个包装器脚本作为我们使用 Kubernetes 运行的 php-fpm docker 容器的 CMD 效果很好.

Regardless, this wrapper script works well as the CMD for our php-fpm docker container that we're running with Kubernetes.

这篇关于Nginx/PHP FPM 优雅停止(SIGQUIT):没那么优雅的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆