Подтвердить что ты не робот

Nginx/PHP FPM изящная остановка (SIGQUIT): не очень грациозная

Запуск nginx 1.9. */PHP 7.0. * (но точно такое же поведение в 5.6. * также)

Попытка изящно прекратить компиляцию PHP-FPM/nginx для закрытия node во время обслуживания. Для этого я отправляю SIGQUIT в php-fpm, который должен обеспечивать изящное завершение работы.

Чтобы проверить это, я сделал немой script

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

Протестировано локально с помощью следующего 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

Желательно: в середине любого запроса на рейс, когда запрашивается изящное завершение, текущие запросы должны заканчиваться, но любые дополнительные запросы должны быть неудачными.

К сожалению, когда я пытаюсь вызвать это поведение, отправив SIGQUIT (http://manpages.ubuntu.com/manpages/precise/man8/php5-fpm.8.html) в главный процесс PHP-FPM:

kill -s SIGQUIT $FPMPID

Соединение немедленно падает, в результате появляется 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

Любые советы? Я хотел бы сделать этот кусок системы максимально плавным. Спасибо!

4b9b3361

Ответ 1

После того, как я некоторое время боролся с этой ситуацией, я считаю, что нашел магическую настройку конфигурации, чтобы дочерние процессы завершали обработку запросов до их смерти.

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

process_control_timeout

Ограничение времени для дочерних процессов, ожидающих реакции на сигналы от мастера

В принципе, установив это как-то вроде 10s, дочерний процесс будет долго ждать, когда обрабатывает существующие запросы до выхода.

К сожалению, кажется, что мастер-процесс php-fpm завершается немедленно, поэтому, вдохновленный кодом здесь, я написал обертку 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 не будет удален (предположительно одним из дочерних процессов? Я все еще не понимаю, как он был удален).

Независимо от того, эта оболочка script хорошо работает как CMD для нашего контейнера docker php-fpm, который мы запускаем с Kubernetes.