Долгий скрипт на Nginx, php5-fpm. Ошибка 504 через 60 сек. Куда смотреть?

Есть долгоиграющий php-скрипт - порядка 3-х минут работает.
Через php scriptname.php отрабатывает.

Форум работает отлично, кроме этого скрипта.
Кусок конфига nginx:
location ~ \.php$ {
                ...
                fastcgi_read_timeout 600;
                ...
        }


Браузер при обращении к скрипту выдает через минуту: "504 Gateway Time-out"

в логе ngnix:
2014/11/23 05:21:05 [error] 8534#0: *1 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.1.41, server: server.ru, request: "GET /scriptname.php HTTP/1.0", upstream: "fastcgi://unix:/var/run/php5-fpm.sock", host: "server.ru"


phpinfo() утверждает, что max_execution_time = 0

Кто еще может ограничивать время выполнения скрипта? Куда копать?
  • Вопрос задан
  • 7470 просмотров
Решения вопроса 1
@neolink
ну раз получаете ответ c 504 значит тюнить надо nginx
fastcgi_connect_timeout
также возможно придется поднять keepalive_timeout

а вообще перенесите выполнение этого скрипта на cron
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
benbor
@benbor
Помог ответ - не забудь лайкнуть
Где вы взяли phpinfo? в php5-fpm или в cli? подозреваю, раз
php scriptname.php
работает нормально, то значение вы достали из cli .
1. Конфиг ищите в /etc/php5/fpm/php.ini
2. Либо наш любимый быдлокод
ini_set('max_execution_time', 0);
(если эту дерективу можно менять в рантайме.... просто не помню)
UPD:
Также есть переменная для php5fpm пула (файл точно не помню , вроде этот /etc/php5/fpm/pool.d/your_pool)
request_terminate_timeout = 300
Ответ написан
alekciy
@alekciy
Вёбных дел мастер
Максимальное время которое nginx ждет ответ от бэкэнда - 75 секунд. Причем это захардкожено в коде самого nginx. Это предельная величина директивы конфига fastcgi_read_timeout (которая по умолчанию как раз 60 секунд). Нужно более долгое время - сбрасывайте буфера на бэкэнде не реже этого времени. Я так желаю:
// отправляем данные nginx-у что бы не выйти за fastcgi_read_timeout
$output_buffer = ob_get_length();
if ( !empty($output_buffer) ) {
    flush();
    ob_flush();
}
Ответ написан
@VovanZ
Если вам нужно, чтобы скрипт просто отработал, и не нужно получать резутат в браузере, то можно установить ignore_user_abort(true) (php.net/manual/ru/function.ignore-user-abort.php), чтобы скрипт доработал после того, как nginx перестает ждать ответа, или же прервать ожидание самому, с помощью fastcgi_finish_request() (php.net/manual/ru/function.fastcgi-finish-request.php) и после этого доделать всё, что надо.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы