it-swarm.com.ru

NginX выдает ошибку HTTP 499 через 60 секунд, несмотря на настройки. (PHP и AWS)

В конце прошлой недели я заметил проблему в одном из моих средних экземпляров AWS, когда Nginx всегда возвращает ответ HTTP 499, если запрос занимает более 60 секунд. Запрашиваемая страница представляет собой скрипт PHP

Я потратил несколько дней, пытаясь найти ответы, и перепробовал все, что я могу найти в Интернете, включая несколько записей здесь, о переполнении стека, ничего не работает.

Я попытался изменить настройки PHP, настройки PHP-FPM и настройки Nginx. Вы можете увидеть вопрос, который я поднял на форумах NginX в пятницу ( http://forum.nginx.org/read.php?9,237692 ), хотя он не получил ответа, поэтому я надеюсь, что могу быть смог найти ответ здесь, прежде чем меня заставят вернуться на Apache, который, я знаю, просто работает.

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

Мне удалось воспроизвести проблему с помощью свежего экземпляра NginX micro AWS, используя PHP 5.4.11.

Чтобы помочь всем, кто хочет увидеть проблему в действии, я проведу вас через настройку, которую я провел для последнего тестового сервера Micro.

Вам нужно будет запустить новый экземпляр AWS Micro (чтобы он был бесплатным) с помощью AMI ami-c1aaabb5

Эта запись Pastebin имеет полную настройку для запуска, чтобы отразить мою тестовую среду. Вам просто нужно изменить example.com в конфигурации NginX в конце

http://Pastebin.com/WQX4AqEU

После настройки вам просто нужно создать пример файла PHP, который я тестирую и который

<?php
sleep(70);
die( 'Hello World' );
?>

Сохраните это в webroot и затем протестируйте. Если вы запустите скрипт из командной строки, используя php или php-cgi, он будет работать. Если вы обращаетесь к сценарию через веб-страницу и подключаете журнал доступа /var/log/nginx/example.access.log, вы заметите, что получите ответ HTTP 1.1 499 через 60 секунд.

Теперь, когда вы видите тайм-аут, я попытаюсь обойти некоторые изменения конфигурации, которые я внес как в PHP, так и в NginX, чтобы попытаться обойти это. Для PHP я создам несколько файлов конфигурации, чтобы их можно было легко отключить

Обновите конфигурацию FPM PHP, чтобы включить внешние конфигурационные файлы

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), и добавляю следующие параметры в директиву server.

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;

Наконец, я добавляю следующее в раздел location ~ .php $ каталога dir сервера.

fastcgi_read_timeout 360;
fastcgi_send_timeout 360;
fastcgi_connect_timeout 1200;

Перед повторным запуском скрипта запустите nginx и php-fpm, чтобы убедиться, что новые настройки выбраны. Затем я пытаюсь получить доступ к странице и все еще получаю запись HTTP/1.1 499 в файле NginX example.error.log.

Итак, где я иду не так? Это работает только на Apache, когда я устанавливаю максимальное время выполнения PHP 2 минуты.

Я вижу, что настройки PHP были выбраны путем запуска phpinfo () со страницы, доступной через Интернет. Я просто не понимаю, я на самом деле думаю, что слишком много было увеличено, так как для этого просто нужно изменить max_execution_time, default_socket_timeout в PHP, а также fastcgi_read_timeout в NginX в пределах только местоположения сервера -> директивы.

Обновление 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');
?>

Если я запускаю сценарий с веб-страницы, то вижу, что содержимое файла будет установлено на первую строку. Через 60 секунд ошибка появляется в журнале NginX. Через 10 секунд содержимое файла изменяется на 2-ю строку, доказывая, что PHP завершает процесс.

Обновление 2

Включение fastcgi_ignore_client_abort; изменяет ответ с HTTP 499 на HTTP 200, хотя конечному клиенту ничего не возвращается.

Обновление 3

После установки Apache и PHP (5.3.10) прямо в коробку (с помощью apt), а затем увеличения времени выполнения проблема, по-видимому, также возникает в Apache. Симптомы такие же, как у NginX сейчас, ответ HTTP200, но фактическое время ожидания клиентского соединения истекло.

Я также начал замечать в журналах NginX, что если я тестирую с помощью Firefox, он делает двойной запрос (например, PHP скрипт выполняется дважды, когда дольше 60 секунд ). Хотя это, кажется, клиент, запрашивающий после сбоя сценария

51
TFAtTheMoon

Причиной проблемы являются упругие балансировщики нагрузки на AWS. По умолчанию время ожидания истекает через 60 секунд бездействия, что является причиной проблемы.

Так что это был не NginX, PHP-FPM или PHP, а балансировщик нагрузки.

Чтобы это исправить, просто перейдите на вкладку «Описание» ELB, прокрутите вниз и нажмите ссылку «(Изменить)» рядом со значением, которое говорит «Время простоя: 60 секунд»

59
TFAtTheMoon

Я думал, что оставлю свои два цента. Во-первых, проблема не связана с php (все еще может быть связана с php, php всегда меня удивляет: P). Это уж точно. В основном это вызвано тем, что сервер проксирован самому себе, более конкретно проблема имен хостов/псевдонимов, в вашем случае это может быть балансировщик нагрузки, запрашивающий nginx, а nginx вызывает обратный вызов балансировщика нагрузки, и он продолжает работать в этом направлении. 

У меня возникла похожая проблема с nginx в качестве балансировщика нагрузки и Apache в качестве веб-сервера/прокси

1
Waheed

Не уверен, что кто-то еще сталкивался с этим, но для меня это произошло после того, как я поставил / в конце моего экземпляра url. Это дало 499 error и только после того, как я удалил /, это дало мне 200, и все прошло хорошо.

0
Souvik Ray

На самом деле я столкнулся с той же проблемой на одном сервере и понял, что после изменений конфигурации nginx я не перезагружал сервер nginx, поэтому при каждом обращении к URL-адресу nginx я получал 499 http ответ. После перезапуска nginx он начал нормально работать с ответами http 200.

0
Rajeev kumar

Вам нужно найти место, где живут проблемы. Я не знаю точного ответа, но давайте попробуем найти его.

У нас есть 3 элемента: nginx, php-fpm, php. Как вы сказали, те же настройки php под Apache - это нормально. Разве это не то же самое? Вы пробовали Apache вместо nginx на той же ОС/Хост/и т.д.?

Если мы увидим, что php не подозревает, у нас есть два подозреваемых: nginx и php-fpm.

Чтобы исключить nginx: попробуйте настроить такую ​​же «систему» ​​на Ruby. Смотрите https://github.com/garex/puppet-module-nginx , чтобы получить идею установить простейшую установку Ruby. Или воспользуйтесь гуглом (может быть, будет еще лучше).

Мой главный подозреваемый здесь php-fpm.

Попробуйте поиграть с этими настройками:

  • php-fpm`s request_terminate_timeout
  • nginx`s fastcgi_ignore_client_abort
0
gaRex