Подтвердить что ты не робот

Сбой PHP-FPM при слишком большом количестве пользователей при выполнении тяжелой работы

У меня есть сервер под управлением Apache/2.2.22 (Debian), PHP 5.6.17 как FPM и MySQL 5.6.25.

Проект выполняется с использованием CMS под названием Redaxo (я не думаю, что это важно, но я все равно скажу). В Redaxo есть некоторые функции, которые занимают некоторое время (например, удаление кеша и перестройка занимает 1-2 минуты). В это время, когда другие пользователи приходят на сайт, FPM падает с помощью 500 Internal Server Error, и мне приходится перезагружать страницу несколько раз, пока ошибка сервера не исчезнет, ​​и процесс завершен.

Я заметил, что это произойдет только в том случае, если слишком много пользователей находятся на сайте в одно и то же время и только при выполнении тяжелых операций.

10 пользователей в то же время просто занимаются серфингом = Нет проблемы
10 пользователей в то же время просто занимаются серфингом, а удаление кеша = 500 Ошибка для всех.

Я проверил это, запретив веб-сайт для всех, кроме меня (.htaccess deny/allow with ip). Затем я сделал тяжелую операцию и не испытывал никаких проблем. Как только несколько человек были на сайте снова, проблема была там снова.

Что это может быть? Какая информация вам нужна от меня?

Эти значения устанавливаются (не комментируются) в php-fpm.conf

[global]
pid = /run/php5-fpm.pid
error_log = /var/log/php5-fpm.log
emergency_restart_threshold = 0
include=/etc/php5/fpm/pool.d/*.conf

Эти значения устанавливаются (не комментируются) в конкретном проекте fpm.conf

[projectname]
user = projectname
group = projectname

listen = /var/run/php5-fpm-projectname.sock
listen.owner = projectname
listen.group = projectname
listen.mode = 0660

pm = dynamic
pm.max_children = 150
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 30

chdir = /

php_value[upload_max_filesize] = 128M
php_value[max_post_size] = 128M
php_value[max_execution_time] = 180
php_value[memory_limit] = 256M

script, когда он терпит неудачу, сильно влияет на создание MySQL и файлов, если это помогает? Но он довольно большой, поэтому я не уверен, что я должен опубликовать его здесь? Или, если это даже проблема?

В журнале ошибок apache указан либо этот

[Tue Feb 09 10:54:01 2016] [error] [client {IP}] (104)Connection reset by peer: FastCGI: comm with server "/fcgi-bin-php5-fpm-projectnmae" aborted: read failed
[Tue Feb 09 10:54:01 2016] [error] [client {IP}] FastCGI: incomplete headers (0 bytes) received from server "/fcgi-bin-php5-fpm-projectnmae"

или

[Tue Feb 09 11:00:46 2016] [error] [client {IP}] FastCGI: incomplete headers (0 bytes) received from server "/fcgi-bin-php5-fpm-projectname"
[Tue Feb 09 11:00:48 2016] [error] [client {IP}] (104)Connection reset by peer: FastCGI: comm with server "/fcgi-bin-php5-fpm-projectname" aborted: read failed

fpm-log говорит следующее. Конечно, всегда разные тайминги

[10-Feb-2016 09:40:59] WARNING: [pool projectname] child 10970 exited on signal 7 (SIGBUS) after 50.186611 seconds from start
[10-Feb-2016 09:40:59] NOTICE: [pool projectname] child 11092 started

Иногда там появляется предупреждение, подобное этому

[09-Feb-2016 11:00:41] WARNING: [pool projectname] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 6 total children
[09-Feb-2016 11:00:42] WARNING: [pool projectname] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 16 children, there are 0 idle, and 7 total children

Вот еще информация об отладке

[18-Feb-2016 17:42:01] WARNING: [pool projectname] child 9088 exited on signal 7 (SIGBUS) after 70.130564 seconds from start
[18-Feb-2016 17:42:01] NOTICE: [pool projectname] child 9205 started
[18-Feb-2016 17:43:55] WARNING: [pool projectname] child 9099 said into stderr: "NOTICE: PHP message: PHP Notice:  Undefined offset: 1181 in /var/www/projectname/htdocs/redaxo/include/classes/class.ooarticle.inc.php on line 44"
[18-Feb-2016 17:43:55] WARNING: [pool projectname] child 9099 said into stderr: "NOTICE: PHP message: PHP Warning:  Invalid argument supplied for foreach() in /var/www/projectname/htdocs/redaxo/include/classes/class.ooredaxo.inc.php on line 134"
[18-Feb-2016 17:43:55] WARNING: [pool projectname] child 9099 exited on signal 7 (SIGBUS) after 183.838886 seconds from start
[18-Feb-2016 17:43:55] NOTICE: [pool projectname] child 9330 started
[18-Feb-2016 17:44:00] WARNING: [pool projectname] child 9101 exited on signal 7 (SIGBUS) after 188.987954 seconds from start
[18-Feb-2016 17:44:00] NOTICE: [pool projectname] child 9336 started
4b9b3361

Ответ 1

Это может быть следствием некоторой проблемы с блокировкой на вашем сервере MySQL.

Вам нужно подключиться к хосту MySQL во время задержки.

  • Если вы не можете подключиться, у вас заканчивается количество разрешенных одновременных подключений вашего сервера MySQL или вашего пользователя.

  • Если вы можете подключиться, вы должны увидеть, что возвращает команда mysql "show processlist". Теперь у вас есть 2 варианта:

    • Многие "Ожидание блокировки кеша запросов": это потребует изменения некоторой конфигурации вашего сервера MySQL. (это может быть вызвано избыточным кешем запросов)

    • У вас есть запрос, который берет все ресурсы, которые вам придется оптимизировать.

Ответ 2

Если у вас много доступной оперативной памяти (например, более 16 ГБ), я бы предположил, что у вас закончились ресурсы, и это вызывает ошибку 500.

В вашей конфигурации говорится, что вы можете создавать до 150 процессов PHP-FPM, и каждый может использовать 256 МБ памяти - это само по себе позволяет серверу PHP-FPM использовать более 38 ГБ памяти, а если это не доступно, вызывают ошибку 500.

Рассчитайте, что каждый сервер может использовать память, а затем установите его правильно. Требует ли эта CMS до 256 МБ памяти? Может ли он работать с меньшим объемом памяти (например, 32 МБ)? Если MySQL, Apache и Nginx находятся на этом же сервере, отделите память, которую они будут использовать, затем установите правильное значение для pm.max_children и php_value[memory_limit].

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

Если вы можете сказать, сколько у вас памяти, я могу помочь вам в настройке этих чисел.

Также было бы полезно узнать, сколько памяти доступно до того, как вы выпустили удаление кеша и сколько доступно во время его запуска - возможно, это слишком много памяти и удушение других процессов (и если он использует PHP -CLI, он может не иметь ограничения по памяти).

Ответ 3

Каждый раз, когда сервер зависает, вы можете увидеть другую ошибку, если php и/или Apache достигнут ограничений.

Если ваш хост является Unix/Linux, можете ли вы проверить результаты команды $ top, в то время как CMS выполняет какие-либо тяжелые задания?

Если вы видите, что память исчерпана, большая часть памяти подкачки заполнена и процессор наверху, попробуйте настроить memory_limit php.ini для распределения ресурсов. Но, вероятно, вам нужно увеличить ресурсы, память и процессор.

Если память и процессор не заняты, возможно, вы назначили меньше памяти, как ожидалось, на php. Вы можете запускать больше рабочих станций php-fpm, уменьшать ограничение памяти для каждого процесса,... см. http://linuxbsdos.com/2015/02/17/how-to-reduce-php-fpm-php5-fpm-ram-usage-by-about-50/. Также обратите внимание на конфигурацию памяти Apache и CPU.

Ответ 4

Я смотрел на это уже несколько дней и, наконец, решил добавить свои 2 цента.

Я использую FPM в течение длительного времени, и это замечательно, но для получения масштабируемой конфигурации это еще одна история. Там много, что может пойти не так, что вызвало вашу проблему, но у меня есть одно подозрение.

Я хочу сосредоточиться на ошибках PHP, появляющихся в вашем выпуске, потому что они указывают, что что-то идет не так, как должно быть. Мне интересно, если вы очищаете свой кеш и пользователи просматриваете сайт, они одновременно вытягивают неполные данные, потому что некоторая информация удаляется или в процессе перестройки. Вы даже можете увидеть ситуацию, когда кеш удаляется, а новые вещи кешируются одновременно. Я не смотрел код CMS для удаления кеша, но ошибки PHP, которые вы показали, указывают на то, что некоторые недопустимые данные извлекаются в процессе.

Можно попытаться явно заблокировать таблицы до удаления кеша, а затем освободить их. Таким образом, пользователь не может читать или записывать данные во время удаления. В любом script, который вы вызываете для очистки кеша, попробуйте добавить запрос LOCK TABLES articles WRITE, othertable WRITE, anyothertable WRITE. Это предотвратит чтение других сессий (пользователей) при чтении или обновлении этих таблиц во время очистки кэша.

Пользователи нетерпеливы, если они пытаются загрузить страницу и не дают им никакой обратной связи, они часто пытаются перезагрузить или вернуться назад и нажать другие ссылки. Это может привести к увеличению количества процессов FPM. Если 10 пользователей обновляются 5 раз, теперь у вас есть 50 дополнительных процессов, а также зависание, что ухудшает ситуацию.

- Другие вещи

Увеличьте ProxyTimeout или Timeout в Apache. Если у вас есть script, который может работать некоторое время, Apache завершит соединение, если он не получит никаких данных за определенное количество времени (что может быть в порядке). Если для очистки кеша требуется 5 минут, и ничего не возвращается PHP до тех пор, пока он не завершится, и у Apache будет время ожидания 120 секунд, оно прекратит соединение до того, как оно завершится, что приведет к таймауту, как вы видите. У меня много сайтов, которые могут делать вещи в течение 10 минут, поэтому мой Timeout в Apache составляет 600 секунд. Это позволяет PHP-запросам заканчиваться без нарушения.

Что-то еще, что я заметил, это то, что вы используете сокеты домена unix для связи FPM. Это может быть хорошо, но они плохо масштабируются на очень загруженных сайтах. Вместо этого я бы предложил использовать TCP-сокет. listen = 127.0.0.1:9000 Затем вам нужно будет изменить Apache для подключения с использованием tcp вместо сокета домена.

Установите listen.backlog, чтобы соединения могли быть поставлены в очередь при занятости. Вероятно, вам также потребуется настроить значение ядра net.core.somaxconn с помощью sysctl, так как оно обычно довольно низкое.

Apache MPM: переключитесь на MPM worker, если вы еще не используете его. Поскольку вы используете FPM, рабочий - очень эффективный MPM для Apache, намного лучше, чем prefork (часто по умолчанию). Обязательно настройте его на свои нужды (например, настройки серверов, потоков и MaxRequestWorkers соответственно).

- Закрытие

Я не думаю, что здесь что-то слишком сложное, первое, на что я бы посмотрел, - это то, что кеш-удаление может завершиться без прерывания. Даже если это означает, что пользователи видят страницу обслуживания на пару минут или их запросы блокируются в течение короткого времени до ее завершения, если она позволяет избежать 500 и ошибок, это небольшая цена для оплаты.

Я честно думаю, что есть проблема с удалением кеша и просмотра пользователями, которые влияют на процесс и заставляют вещи занимать больше времени, чем нужно или ломаются.

Сообщите мне, если у вас есть какие-либо вопросы или вы можете связаться со мной.

Ответ 5

Эта ошибка обычно вызвана idle_timeout (который по умолчанию равен 30 секундам) или максимальным количеством дочерних процессов. Это может быть вызвано тем, что кто-то запустил длинный script (например, удаление вашего кеша) и закрыл их соединение (/браузер) до завершения script. Или это может быть вызвано ограничением памяти php.

В вашем случае FastCGI запускает свою обертку обработки, выполняет команду и время до завершения процесса, которое разрешается в соединении, которое рассматривается как reset одноранговым узлом.

Но также возможно, что максимальное количество детей (maxProcesses) будет достигнуто. Если все дети в настоящее время активны, а на ваш сервер добавлен дополнительный запрос/подключение, дети ограничены maxProcesses, к которым FastCGI не будет делиться активными дочерними элементами, поэтому он должен либо прекратить процесс, либо начать новый дочерний процесс, либо отбросить запрос, прежде чем вы сможете что-то сделать (это зависит от ваших конфигураций).

Пример оболочки FastCGI:

PHP_FCGI_MAX_REQUESTS=10000
export PHP_FCGI_MAX_REQUESTS
PHP_FCGI_CHILDREN=0 #no limit
export PHP_FCGI_CHILDREN

Дополнительная информация о настройках FastCGI: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html

Чтобы увеличить ваш поиск memory_limit в php.ini для memory_limit, увеличьте его до ваших потребностей.

Дополнительная информация о memory_limit: http://php.net/manual/en/ini.core.php#ini.memory-limit

Ответ 6

  • Чтобы увеличить memory_limit и увеличить max_execution_time
    • Обновить время чтения_буфера в my.ini
    • Установить правильное индексирование в таблицу