У меня Apache2 с PHP + PHP-FPM настроен в соответствии с:
http://wiki.apache.org/httpd/PHP-FPM
Я пишу сценарий, выполнение которого на внутреннем виртуальном хосте займет много времени, но время ожидания постоянно истекает, все работает безупречно, если сценарий выполняется менее чем за 30 секунд.
Мой журнал apache сообщает мне:
[Wed Apr 17 21:57:23.075175 2013] [proxy_fcgi:error] [pid 9263:tid 140530454267648] (70007)The timeout specified has expired: [client 58.169.202.172:49017] AH01075: Error dispatching request to :, referer:
При попытке запустить скрипт мне дается 503 Service Unavailable
ровно через 30 секунд выполнения. Логически это означало бы, что у меня есть директива тайм-аута или настройка, установленная на 30 секунд, но у меня они есть в конфигурации моего Vhost:
Timeout 600
<IfModule proxy_module>
ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9001/home/pyrokinetiq/scripts/$1 timeout=600
ProxyTimeout 600
</IfModule>
(php-fpm у меня работает на порту 9001)
Я также попытался разместить Timeout
и ProxyTimeout
в httpd.conf
без разницы.
Кажется, есть еще одна настройка тайм-аута, специфичная для mod_proxy_fcgi
, но я не могу его найти. Я установил Apache2 httpd из официального архива, похоже, ни один из модов не содержит никаких файлов конфигурации.
Если кто-нибудь может указать мне правильное направление, я буду очень признателен.
Я окончательно исправил эту проблему после тестирования нескольких параметров конфигурации. Я протестировал решение дважды, удалив все предыдущие изменения. Мне нужен был только один параметр, чтобы это исправить.
Для последних версий httpd и mod_proxy_fcgi вы можете просто добавить timeout=
до конца ProxyPassMatch
строка, например:
ProxyPassMatch ^/(.+\.php.*)$ fcgi://127.0.0.1:9000/<docroot>/$1 timeout=1800
Для более старых версий это было немного сложнее, например:
<Proxy fcgi://127.0.0.1:9000>
ProxySet timeout=1800
</Proxy>
ProxyPassMatch ^/(.+\.php.*)$ fcgi://127.0.0.1:9000/<docroot>/$1
Мне нужно было добавить директиву Proxy, чтобы установить тайм-аут на 30 минут. В некоторых приложениях, обычно при работе с базой данных, есть подпрограммы, выполнение которых может занять более 10 минут. Я временно установил тайм-аут на 30 минут, чтобы они закончились. Особенно полезно при использовании мастера установки, который занимает слишком много времени (по моему скромному мнению).
Кстати, исходные данные, которые помогли мне решить эту проблему, были найдены в следующих URL-адрес.
Я хотел отметить, что хотя этот ответ отлично работает для старых версий, в последних версиях Apache 2.4 он ломается с кодом ошибки AH00526. ProxyPass
и ProxyPassMatch
или <Proxy>
и <ProxyMatch>
не могут использоваться вместе с одним и тем же именем исполнителя. Раньше это работало нормально, поэтому не знаю, было ли это изменено по дизайну или это ошибка.
В любом случае вы можете исправить это, только используя ProxyPassMatch с параметром timeout = 120 (или любым другим, как вам нужно), например:
ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9001/path/to/webroot/$1 timeout=120
У меня Apache 2.4.6, но патч исправить это предусмотрено в Apache> = 2.4.8. Ключевым моментом здесь является Начало ваш вывод немедленно, чтобы Apache (mod_proxy_fcgi) думал, что соединение активно.
Например, я использую PHP, и запрос к БД для моего вызова AJAX занимает> 30 секунд. Поскольку я знаю, что общий ответ будет «Content-Type: application / json», я немедленно отправляю этот заголовок.
#1: Start output immediately
#Note: Sending the header is innocuous
# it can be changed later using the $replace parameter
# (see #3)
header( 'Content-Type: application/json' );
#2: Run slow query
mysql_query( "SELECT * FROM giant_table" );
#3: Change header as needed
header( 'Content-Type: application/csv', true );
#output content
Я заметил, что вы используете PHP-FPM. Я тоже им пользуюсь, но с Apache 2.4.6.
Предполагая, что проблема существует в течение некоторого времени, похоже, что значение тайм-аута для mod_proxy_fcgi
является жестко закодированный. Я написал то, что нашел Вот
Не должно быть:
<IfModule mod_proxy.c>
Убедитесь, что для параметра max_execution_time php.ini также установлено значение 600. (проверьте phpinfo () на действующей странице, чтобы убедиться, что вы видите фактическое используемое значение)
Как сказала Дженни, установите настройку php-fpm
request_terminate_timeout 610s
(обратите внимание на букву s в конце)
Сам mod_proxy_fcgi не так много настраивает, как вы можете видеть на странице apache. http://httpd.apache.org/docs/current/mod/mod_proxy_fcgi.html
Включите также ведение журнала отладки php-fpm, чтобы вы могли видеть, где оно истекает. http://php-fpm.org/wiki/Configuration_File (также включите catch_workers_output)
И включите ведение журнала уровня отладки для модулей mod_proxy и mod_proxy_fcgi, поскольку вы используете apache 2.4. Очень приятная функция, включайте только те модули, которые вам нужны: http://httpd.apache.org/docs/current/mod/core.html#loglevel
Если это не помогло, опубликуйте свой файл конфигурации php-fpm.
В крайнем случае, может быть, какой-то демон убивает длительный процесс?
Поскольку вы исправили настройки тайм-аута в apache, это не должно быть проблемой. Вторым местом для поиска может быть любое сетевое оборудование, но, поскольку вы проксируете свой собственный сервер, это тоже маловероятно. Таким образом, оставшееся место для просмотра - это внутренний сервер.
Ih файл конфигурации для php-pfm, ищите
; This is a hard kill switch on php execution. It ignores the
; max_execution_time that can be set/changed with php_ini. Basically
; it avoids timeout issues between apache and php-fpm.
request_terminate_timeout=30
Он должен быть таким же или немного ниже тайм-аута в apache.
В дополнение к таймауту установите enablereuse = off. Я обнаружил, что когда он был на некоторых запросах, долго работающие скрипты работали правильно, а другие были убиты раньше.
Эта почта изменил для меня всю сделку.
Похоже, что mod_reqtimeout Apache не будет использовать значение по умолчанию.
Добавьте следующие строки в свой httpd.conf файл:
<IfModule reqtimeout_module>
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
</IfModule>