В конце прошлой недели я заметил проблему на одном из моих серверов, где Nginx всегда возвращает ответ HTTP 500, если запрос занимает более 60 секунд. Запрошенная страница представляет собой скрипт PHP
Я провел несколько дней, пытаясь найти ответы, и попробовал все, что я могу найти в Интернете, включая несколько записей здесь, в Stack Overflow, ничего не работает.
- $ _SERVER не дает значения
- Nginx переписать не работает с расширением .php
- Ошибка nginx подключиться к php5-fpm.sock не удалось (13: отказ от прав)
- php-fpm разбился, когда curl или file_get_contents запросили https-url
- Сложность Ioncube с PHP 5.5
Я пробовал изменять настройки PHP, настройки PHP-FPM и настройки Nginx. Увеличивал время ожидания и выполнение скриптов, но все сводилось к тому что где-то сидит конфиг который завершает выполнение через 60с. Это не та же проблема, что и ошибки HTTP 500 в других записях.
Чтобы помочь любому, кто хочет увидеть проблему в действии, я собираюсь провести вас через настройку, которую я запускал для последнего тестового сервера Micro.
Сделал образец файла 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 я создам несколько файлов конфигурации, чтобы их можно было легко отключить
Обновите PHP FPM Config, чтобы включить внешние файлы конфигурации
sudo echo ' include=/usr/local/php/php-fpm.d/*.conf ' >> /usr/local/php/etc/php-fpm.conf
в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, который мы создали ранее, и добавьте следующие параметры в директиву сервера
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;
Прежде чем повторять сценарий, запустите nginx и php-fpm, чтобы убедиться, что новые настройки были подняты. Затем я пытаюсь получить доступ к странице и все еще получаю запись HTTP / 1.1 499 в файле NginX example.error.log.
Итак, где я иду не так? Это просто работает на apache, когда я устанавливаю максимальное время выполнения PHP до 2 минут.
Я вижу, что настройки PHP были подобраны, запустив phpinfo () с веб-страницы. Я просто не понимаю, я действительно думаю, что слишком много было увеличено, так как это должно было просто потребовать изменения max_execution_time PHP, default_socket_timeout, а также fastcgi_read_timeout от NginX только в директиве location-> server .
Обновление 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 секунд содержимое файла изменяется на вторую строку, доказывая, что PHP завершает процесс.
Обновление 2
Установка fastcgi_ignore_client_abort; изменяет ответ от HTTP 499 на HTTP 200, хотя ничего не возвращается конечному клиенту.
Обновление 3
Установив Apache и PHP (5.3.10) на поле прямо (используя apt), а затем увеличивая время выполнения, проблема также возникает и на Apache. Симптомы такие же, как и у NginX, ответ HTTP200, но фактическое время соединения с клиентом перед раздачей.
Я также начал замечать в журналах NginX, что если я тестирую с помощью Firefox, он делает двойной запрос (например, этот PHP-скрипт выполняется дважды, когда он длится более 60 секунд ). Хотя, похоже, это клиент, запрашивающий при неудачном сценарии.
Я думал, что оставлю свои два цента. Сначала проблема не связана с php (все еще может быть связано с php, php всегда меня удивляет: P). Это уж точно. в основном это вызвано сервером, проксированным для себя, в частности, имена имен хостов / псевдонимов, в вашем случае это может быть балансировка нагрузки, запрашивающая nginx, и nginx обращается к балансировщику нагрузки и продолжает идти таким образом.
Я столкнулся с аналогичной проблемой с nginx в качестве балансировки нагрузки и apache в качестве веб-сервера / прокси-сервера
Вам нужно найти, в каком месте проблемы жить. Я не знаю точного ответа, но просто попробуем его найти.
У нас есть 3 элемента: nginx, php-fpm, php. Как вы сказали, одинаковые настройки php под apache в порядке. Разве это не такая же настройка? Вы пытались apache вместо nginx на той же ОС / хосте / и т. Д.?
Если мы увидим, что php не подозревает, у нас есть два подозреваемых: nginx & php-fpm.
Чтобы исключить nginx: попробуйте настроить ту же «систему» на рубине. См. https://github.com/garex/puppet-module-nginx, чтобы получить представление об установке простейшей рубиновой установки. Или используйте google (возможно, это будет еще лучше).
Мой главный подозреваемый здесь – php-fpm.
Попробуйте сыграть с этими настройками:
- php-fpm `request_terminate_timeout
- nginx`s fastcgi_ignore_client_abort
На самом деле я столкнулся с той же проблемой на одном сервере, и я понял, что после изменений конфигурации nginx я не перезапустил сервер nginx, поэтому с каждым ударом nginx-url я получал ответ 499 http. После перезапуска nginx он начал нормально работать с ответами HTTP 200.