В конце прошлой недели я заметил проблему в одном из средних экземпляров AWS, где Nginx всегда возвращает ответ HTTP 499, если запрос занимает более 60 секунд. Запрошенная страница представляет собой PHP скрипт
Я провел несколько дней, пытаясь найти ответы, и попробовал все, что я могу найти в Интернете, включая несколько записей здесь, в Stack Overflow, ничего не работает.
Я пробовал изменять настройки PHP, настройки PHP-FPM и настройки Nginx. Вы можете увидеть вопрос, который я поднял на форумах NginX в пятницу (http://forum.nginx.org/read.php?9,237692), хотя он не получил ответа, поэтому я надеюсь, что я мог бы найти ответ здесь, прежде чем я вынужден вернуться к Apache, который, как я знаю, просто работает.
Эта не та же проблема, что и ошибки HTTP 500, о которых сообщалось в других записях.
Я смог реплицировать проблему с помощью нового экземпляра micro AWS NginX, используя PHP 5.4.11.
Чтобы помочь любому, кто хочет увидеть проблему в действии, я собираюсь провести вас через настройку, которую я запускал для последнего тестового сервера Micro.
Вам понадобится запустить новый экземпляр AWS Micro (чтобы он был свободен), используя AMI ami-c1aaabb5
Эта запись PasteBin имеет полную настройку для запуска, чтобы отразить мою тестовую среду. Вам просто нужно изменить example.com в конфигурации NginX в конце
После этой настройки вам просто нужно создать образец PHP файла, который я тестирую с помощью
<?php
sleep(70);
die( 'Hello World' );
?>
Сохраните это в webroot, а затем проверьте. Если вы запустите script из командной строки, используя php или php-cgi, он будет работать. Если вы перейдете к script через веб-страницу и закроете журнал доступа /var/log/nginx/example.access.log, вы заметите, что получите ответ HTTP 1.1 499 через 60 секунд.
Теперь, когда вы можете увидеть таймаут, я рассмотрю некоторые изменения конфигурации, которые я сделал как для PHP, так и для NginX, чтобы попытаться обойти это. Для PHP я создам несколько файлов конфигурации, чтобы их можно было легко отключить
Обновить конфигурацию PHP FPM для включения внешних файлов конфигурации
sudo echo '
include=/usr/local/php/php-fpm.d/*.conf
' >> /usr/local/php/etc/php-fpm.conf
Создайте новую конфигурацию PHP-FPM, чтобы переопределить тайм-аут запроса
sudo echo '[www]
request_terminate_timeout = 120s
request_slowlog_timeout = 60s
slowlog = /var/log/php-fpm-slow.log ' >
/usr/local/php/php-fpm.d/timeouts.conf
Измените некоторые глобальные параметры, чтобы обеспечить время аварийного перезапуска 2 минуты
# Create a global tweaks
sudo echo '[global]
error_log = /var/log/php-fpm.log
emergency_restart_threshold = 10
emergency_restart_interval = 2m
process_control_timeout = 10s
' > /usr/local/php/php-fpm.d/global-tweaks.conf
Затем мы изменим некоторые параметры PHP.INI, снова используя отдельные файлы
# Log PHP Errors
sudo echo '[PHP]
log_errors = on
error_log = /var/log/php.log
' > /usr/local/php/conf.d/errors.ini
sudo echo '[PHP]
post_max_size=32M
upload_max_filesize=32M
max_execution_time = 360
default_socket_timeout = 360
mysql.connect_timeout = 360
max_input_time = 360
' > /usr/local/php/conf.d/filesize.ini
Как вы можете видеть, это увеличивает тайм-аут сокета до 3 минут и помогает регистрировать ошибки.
Наконец, я отредактирую некоторые настройки NginX, чтобы увеличить тайм-аут той стороны
Сначала я редактирую файл /etc/nginx/nginx.conf и добавляю его в директиву http fastcgi_read_timeout 300;
Затем я редактирую файл /etc/nginx/sites -enabled/example, который мы создали ранее (см. запись pastebin), и добавьте следующие параметры в директиву сервер
client_max_body_size 200;
client_header_timeout 360;
client_body_timeout 360;
fastcgi_read_timeout 360;
keepalive_timeout 360;
proxy_ignore_client_abort on;
send_timeout 360;
lingering_timeout 360;
Наконец, я добавлю следующее в папку ~.php $раздела сервера dir
fastcgi_read_timeout 360;
fastcgi_send_timeout 360;
fastcgi_connect_timeout 1200;
Прежде чем повторить попытку script, запустите nginx и php-fpm, чтобы убедиться, что новые настройки были подняты. Затем я пытаюсь получить доступ к странице и все еще получаю запись HTTP/1.1 499 в файле NginX example.error.log.
Итак, где я иду не так? Это просто работает на apache, когда я устанавливаю время выполнения PHP max до 2 минут.
Я вижу, что настройки PHP были подняты, запустив phpinfo() на странице, доступной в Интернете. Я просто не понимаю, я на самом деле думаю, что слишком много было увеличено, так как для этого нужно просто PHP max_execution_time, default_socket_timeout, а также NginX fastcgi_read_timeout только в директиве location- > location.
Обновление 1
Проведя еще один тест, чтобы показать, что проблема заключается не в том, что клиент умирает, я модифицировал тестовый файл как
<?php
file_put_contents('/www/log.log', 'My first data');
sleep(70);
file_put_contents('/www/log.log','The sleep has passed');
die('Hello World after sleep');
?>
Если я запустил script с веб-страницы, я могу увидеть, что содержимое файла будет установлено в первую строку. Через 60 секунд в журнале NginX появляется ошибка. Через 10 секунд содержимое файла изменяется на вторую строку, доказывая, что PHP завершает процесс.
Обновление 2
Настройка fastcgi_ignore_client_abort on; изменяет ответ HTTP HTTP 499 на HTTP 200, но ничего не возвращается конечному клиенту.
Обновление 3
Установив Apache и PHP (5.3.10) на поле прямо (используя apt), а затем увеличивая время выполнения, проблема также возникает и на Apache. Симптомы те же, что и сейчас, NginX, ответ HTTP200, но фактическое время соединения с клиентом перед рукой.
Я также начал замечать в журналах NginX, что если я тестирую с помощью Firefox, он делает двойной запрос (например, PHP script выполняется дважды, когда дольше, чем 60 секунд). Хотя это, похоже, является клиентом, запрашивающим