Linux очень много php процессов

Обновлено: 07.07.2024

pm = dynamic – количество дочерних процессов устанавливается динамически, основываясь на следующих директивах: pm.max_children , pm.start_servers , pm.min_spare_servers , pm.max_spare_servers .

pm = ondemand – процессы плодятся по требованию (при необходимости, в отличие от динамического варианта, где pm.start_servers запускаются при запуске сервиса).

pm = static – количество дочерних процессов фиксировано директивой pm.max_children .

…вы можете посмотреть полный список директив php-fpm.conf для получения дополнительной информации.

Менеджер процессов (process manager) PHP-FPM-а схож с CPUFreq Governor

Это может показаться немного не по теме, но я надеюсь связать его с нашей оптимизацией PHP-FPM. Да, все мы когда-то натыкались на проблемы с производительностью процессора, будь то ноутбук, виртуальная машина или выделенный сервер. Помните масштабирование частоты процессора? (CPUFreq governor) Эти параметры, доступные на *nix и Windows, могут повысить производительность и отзывчивость системы путем изменения настройки CPU governor с ondemand на performance . Сейчас давайте сравним описания и поищем сходства:

Governor = ondemand – Динамически увеличивает/уменьшает тактовую частоту процессора в зависимости от загруженности системы. Выводит до максимальной частоты, а потом уменьшает по мере увеличения времени простоя.

Governor = conservative – Похож на ondemand, но более экономный (предпочтение отдаётся меньшим тактовым частотам). Частота растёт более плавно.

Governor = performance – Поддерживает процессор(ы) на максимальной тактовой частоте.

… для дополнительной информации см. полный список настроек CPUFreq governor.

Заметили сходство? Я хотел сначала использовать это сравнение, чтобы более наглядно и лучше описать рекомендацию использовать pm static для PHP-FPM в качестве вашего первого выбора.

Настройка performance в CPU governor – это довольно безопасный прирост производительности, потому что это почти полностью зависит от предела процессора вашего сервера. Но есть несколько побочных эффектов (при постоянном удерживании частоты вашего процессора на 100%) – такие, как нагрев, время автономной работы (ноутбук) и другие. Однако это действительно самый быстрый параметр для вашего процессора.

Использование pm = static для максимальной производительности вашего сервера

Настройка pm = static в PHP-FPM сильно зависит от того, сколько свободной памяти на сервере. В основном, если вы страдаете от нехватки памяти сервера, то pm ondemand или dynamic могут оказаться лучшими вариантами. С другой стороны, если у вас достаточно свободной памяти, вы можете избежать большей части накладных расходов менеджера процессов, установив pm static до максимальной емкости сервера. Другими словами, когда вы делаете расчёты, pm.static нужно установить на максимальное количество PHP-FPM процессов, которые могут выполняться без создания проблем доступности памяти или кеша; однако, не так высоко, чтобы перегрузить процессор(ы) и иметь кучу отложенных операций PHP-FPM-а.

Тут отображаются не все процессы, а только та часть, что вместилась в ваше терминальное окно. В нашем случае отсортированных по %CPU (потреблению процессора). Чтобы увидеть все 100 PHP-FPM процессов, вы можете использовать что-то вроде этого:

Когда использовать pm ondemand и dynamic

Используя режим dynamic , вы можете наткнуться на подобные ошибки:

Вы можете попытаться увеличить/изменить настройки и по-прежнему видеть ту же ошибку. Подобная ситуация описана в этом вопросе на Serverfault. В таком случае, pm.min была слишком низкой, а т. к. трафик сильно колеблется, режим dynamic достаточно сложно настроить правильно. Общий совет: используйте ondemand , как советуют в этом же вопросе. Однако что еще хуже, т. к. ondemand будет завершать процессы в простое вплоть до 0 когда мало трафика, то после вы получите настолько много накладных расходов, насколько скакнёт трафик. Если, конечно, вы не установите время ожидания чрезвычайно высоким. В этом случае вам просто нужно использовать pm = static + высокий pm.max_requests .

Заключение

Когда дело доходит до PHP-FPM, раз вы начали получать серьезный трафик, то режимы ondemand и dynamic могут ограничить пропускную способность из-за свойственного оверхеда. Исследуйте вашу систему и установите количество процессов в наибольшее, с которым справится ваш сервер. Начните с pm.max_children , установленным на основе максимального использования режимов dynamic или ondemand , а затем увеличивайте до точки, где память и процессор остаются не перегруженными. Вы заметите, что с pm = static , т. к. вы держите всё в памяти, всплески трафика со временем будут меньше влиять на всплески загрузки процессора, а показатели загрузки и средней загрузки станут более сглаженными. Средний размер вашего PHP-FPM-процесса будет зависеть от конкретного веб-сервера, требующего ручной настройки, вот почему автоматизированные режимы – dynamic и ondemand – являются более популярными рекомендациями. Надеюсь, это была полезная статья.

Стандартные библиотеки PHP умеют генерировать только целые случайные числа. Однако, возникают задачи где нужно не целое рандомное число с максимально…

Иногда при обработке с помощью PHP больших и не очень данных, можно словить досадную ошибку посреди выполнения скрипта: PHP Fatal…

Процессы в Linux

В программирование бывает необходимость писать программы, которые должны работать непрерывно, причины тому могут быть: непрерывное отслеживание изменений на сайте, длительное выполнение какой-либо операции, веб-сокет сервер и другие. И для небольших программ язык PHP, как никогда подходит лучше всего. Здесь я попытаюсь описать возможные шаги, которые нужно предпринять чтобы написать свою программу работающую в среде Linux. Я предполагаю что Вы уже знакомы с Линукс и слова «консоль» и «ssh» Вас уже не пугают. Примеры команд будут запущены в среде Debian Linux 8.4, с PHP 7. Сам PHP 7 установлен как CLI.

Оглавление

Процесс в Linux

Запуская программу в Unix вы создаёте «процесс», т.е. процессор начинает выполнять инструкции программы. Чтобы не запутаться в названиях «программа» и «процесс» можно представить, что «программа» это некоторая бумага с текстом приказа, а «процесс» это робот который читает приказ и выполняет его. Вполне может быть что процесс может удалить программу, которая его запустила или что процесс запустил другие программы, т.е. вызвал другие процессы.

Запуская программу в Unix процессу присваиваются некоторые параметры, а именно:

* Запуская программу в консоли я использую на конце символ «&», это я делаю для того чтобы после запуска в консоли можно было запускать другие программы, т.е. не быть заблокированным своим процессом.

- Имя - имя процесса формируется из имени программы и параметры его запуска. Т.е. если выполнить в консоли « php sleep.php & » процесс будет называться « php sleep.php » если же выполнить « /usr/local/bin/php sleep.php & », то процесс будет называться « /usr/local/bin/php sleep.php ». Но так бывает не всегда, при желании процесс может задать себе новое какое пожелает. Пример:

Вывод команды ps будет напоминать что-то вроде этого.

Я всё же рекомендую не использовать в имени процесса UTF-8 символы и спец символы, во избежания проблем с операционными системами Unix, без поддержки Unicode на уровне ядра.

- PPID - PID родительского процесса. У каждого процесса есть родитель, т.е. процесс который его запустил. У родительского процесса также может присутстовать родитель и так вверх по иерархии. На самом верху иерархии находится процесс « init » или « systemd », он является родоначальников всех процессов и его запускает само ядро Linux. У процесса всегда есть родитель, если родительский процесс закрывается все потомки родительского процесса «усыновляются» процессом « init » или « systemd ». Если вы запускаете программу через консоль, то родителем процесса будет консольная программа, вероятно « tcsh », « bash » или « zsh ». Посмотреть иерархию процессов можно так:

- UID - UID пользователя, который запустил процесс. После запуска процессу ещё присваивается владелец и группа (почти как у файла) и с правами этого пользователя процесс будет работать. К примеру если мы запустим программу от пользователя «user1» находящегося в группе «group1», то процесс сможет выполнять действия доступные пользователю «user1», и не сможет скажем зайти в папку «/root» или удалить файл, владелец которого является пользователь «user2».

- Аргументы программы - строки указанные в консоле при запуске программы после имени программы через пробел. Например если в консоли запустить программу: «php example.php a b -p1 --test=2», аргументами будут строки «a», «b», «-p1», «--test=2». В PHP аргументы программы можно найти в глобальном массиве $argv, а кол-во аргументов можно найти в глобальной переменной «$argc». Пример:

Закрытие процесса

Если вы запустили программу и программа заблокировала консоль используйте сочетание клавиш « Ctrl + C » и программа завершится. Или если просто хотите вернуться консоль не закрывая программу, то нажмите « Ctrl + Z », а далее « bg ».

Программы Linux для работы с процессами

Программ для работы с процессами множество, я же расскажу о программах которые мне нравятся больше и популярные примеры их использования. Речь пойдёт о программах: ps , pgrep , kill , htop .

- ps - показывает запущенные процессы и сведения по ним. Примеры:

* - Если написать просто «ps -ef | grep "simple.php"», то отобразиться не только нужный нам процесс и сведения о самом нашем процессе «ps» и это может запутать.

- pgrep - ищет процесс по имени и возвращает PID процесса. В отличии от ps не возвращает PID самого себя, а только нужный нам. В большинстве случаев результат программы pgrep используется другими программами. Примеры:

* Если процесс не настроен на «ловлю» этого сигнала процесс завершиться.

- htop - программа для мониторинга процессов в реальном времени. Программа позволяет узнать загруженность системы, а также узнать какие процессы используют большую часть процессорного времени или оперативной памяти. Удобно запускать в отдельном окне и заглядывать туда.

- pstree - показать дерево процессов. Можно посмотреть всю иерархию процессов или всех «предков» процесса.

Непрерывный процесс

Теперь нам нужно добиться того чтобы наш скрипт работал постоянно (а не выключался после запуска), для этого нам достаточно написать бесконечный цикл, к примеру вот так:

Если мы запустим этот скрипт, у нас действительно процесс будет запущен постоянно, но при этом мы получим почти 100% загрузку процессора, т.е. итерации цикла будут выполняться постоянно со 100% скоростью. Чтобы этого избежать нагрузку процессора, но при этом получать отклик необходимо по окончании каждой итерации цикла останавливать скрипт на некоторое количество времени. Для этого можно использовать функции « sleep » или « usleep », при « sleep » указывается время в секундах, а при «usleep» время в микросекундах, т.е. « sleep(2) = usleep(2000000) ». Переделаем наш скрипт:

Здесь «usleep» будет означать, время отклика ваше программы на внешние раздражители (сигналы, сокеты и прочее).Теперь вместо почти 100% загруженности получим почти 0% загруженность процессора при простаивании процесса. Вероятно программа, которая работает в фоне будет не просто выполняться в бесконечном цикле, а ждать поступления определённого события (сигналы, таймер, поступление данных на канал или сокет, изменения в файлах и прочее), здесь же скрипт предоставлен в качестве примера.

Отвязываемся от консоли

Мы научились запускать процессы в режиме ожидания, теперь необходимо чтобы процесс смог самостоятельно работать и не быть «привязанным к консоли». Запуская свои программы в консоли мы можем заметить пока программа выполняется, другие программы запускать в консоли не получается. Есть несколько способов запустить программу в фоновом режиме.

Первый способ:

Используйте символ « & » (Амперса́нд) после набора команды. Пример:

Консоли бывают разные (bash, tcsh, zsh и др.) и некоторые консоли (но не tcsh) при закрытии отправляют процессам специальный сигнал «SIGHUP», после чего программы завершают своё выполнение. Чтобы этого избежать используйте программу «nohup», она гарантирует что после закрытия консоли программы не закроются.

Второй способ:

После запуска программы нажмите сочетание клавиш « Ctrl + Z » и далее команду « bg ». Сочетаниями клавиш мы ставим процесс на «паузу» и командой « bg » «будим» процесс и он продолжает работать работать в фоне.

Третий способ:

Ещё один способ подразумевает что запущенный процесс (родительский процесс) «склонирует» себе подобный процесс (дочерний процесс) т.е. «форкнется» и завершиться. Родительский процесс завершиться, а дочерний процесс продолжит работу, к тому же он усыновляется процессом « init » и перестаёт быть зависимым от консоли. Я считаю этот способ более предпочтительным, т.к. нам теперь нет необходимости на конце писать символ « & » и следить не закроется ли он после закрытия консоли.

Одна программа - один процесс

Запуская нашу программу несколько раз мы будем постоянно «плодить» одинаковые процессы, нам же нужно чтобы программа порождала только один процесс. Чтобы программа запускалась только один раз, нужно чтобы она перед запуском опрашивала систему на поиск себе подобных процессов. Один из способов узнать запущенна ли уже программа это использовать «pid-файл», т.е. файл в котором записан PID запущенного процесса. Определить какой PID текущего процесса можно функцией posix_getpid . Создаётся pid-файл вот так:

Далее при каждом запуске программы, программа будет читать этот файл и на указанный PID будет отправлять сигнал, если ответ придёт утвердительный значит программа уже запущена и запуск повторный не потребуется, если же ответа нет значит можно запускаться. Проверить запущен ли процесс с определённым PID можно функцией « posix_kill », которая отправит сигнал процессу. В функции указать сигнал с номером « 0 ».

Теперь напишем программу, которая будет запускаться только один раз:

Программа запустилась только один раз.

PHP-программа как Unix скрипт

Теперь если запустить файл без указания интерпритатора, то программа запуститься через «/usr/bin/php», если запустить с указанием интерпритатора, то программа запустить через указнный в консоли интерпритатор. Пример:

Есть довольно мощный сервер (выделенный, 4-ядра ксеон, 32 памяти, SSD). На котором по не понятной причине перестает работать php-fpm. В какое-то время он просто перестает отвечать на запросы, а в процессах висит куча его пулов.

и таких 202 штуки.

В логах кроме ошибок nginx ничего нету (php5-fpm лог чистый)

и все в таком духе

конфиг /etc/php5/fpm/php-fpm.conf (коменты удалены)

До недавнего времени, работал на сокетах. Но поскольку проблема проявляется стабильно, попробовал перевести на порты. Результата нет. Не могу понять в чем проблема.


плодит кучу процессов.
Connection timed out

PHP-скрипты работают слишком долго, запросы не успевают отрабатываться.

Для начала — что-то типа

Или под высокой нагрузкой даже меньше, 3-5 сек.

в соответствующем php.ini

и памяти там достаточно.

По логике, суть ситуации в том, что у меня просто выбираются все свободные chldren (которых 200 штук), и новые просто не могут создаться.

Но я не понимаю чем они заняты, и как это посмотреть?



Вот когда у тебя скрипты подвисают, они и ждут по часу каждый :)

Но я не понимаю чем они заняты, и как это посмотреть?

Поставь 5-10-30 секунд. И лови в логах, в каком месте будет ошибка вылетать.

Более точно можно понять с установкой xhprof или xdebug (важно помнить, что когда последний подключен к PHP то тормозит скорость работы почти в 10 раз даже когда выключен).


xdebug (важно помнить, что когда последний подключен к PHP то тормозит скорость работы почти в 10 раз даже когда выключен).

И место на харде быстро заканчивается.


Была такая же трабла с OwenCloud, решилось с обновлением ОС. Полагаю, что проблема в коде.


а может просто к примеру база занимает время и процесс поэтому висит?

Ну у меня счас одно предположение.

Гдето (пока не знаю) где, косяк в коде, который вызывает зацикливание (или просто очень долгую отработку), в какой-то момент, кто-то или что-то, начинает вызывать этот косяк, отсюда забивается все 200 чилдренов, и на нового чилдрена просто нет ресурса.


И место на харде быстро заканчивается.

При выключенном автостарте xdebug — нет :) Но вот скорость падает сильно. Поэтому под нагрузкой — только xhprof.

Есть веб сервер zabbix 3.0 на виртуальной машине под управлением Debian 3.2.0-4-amd64 (vmware 12 ядер 8 гб оперативы). На нём:

NGINX - frontend, Apache - backend, php5.
Mysql на другой физической машине

Нагрузка на серв достаточно большая. В заббиксе огромное множество карт с тысячами элементов (думаю основная проблема именно в них). Пользователей одновременно может работать в районе 100.

Ситуация следующая. Относительно недавно веб сервер стал тормозить.
Плодятся процессы "/usr/sbin/apache -k start". Постоянно. Не зависимо от времени суток и соответсвенно загруженности сервера.

Плодятся они до того момента пока не кончиться память и сервер не перестаёт отвечать.

Ребутаем апач - всё отлично и шустро работает. Сервисы начинают плодиться, но всё равно всё быстро и шустро работает.
Проходит 10 минут, сервисов становится 25, проц загружен на 100% (все ядра по 100), но всё равно веба отвечает достаточно быстро.
Проходит 20 минут, сервисов уже штук 40, но нам пофиг, у нас всё работает круто
Проходит 30 минут, сервисов уже штук 60, мы еще терпим, памяти съедает гигов 5-6, но уже начинаются задержки.
Проходит 50 минут, сервисов уже штук 80, мы не выдерживаем и ощущая реальные тормоза отправляем апач в ребут.

Дальше всё по кругу. Не важно в какое время, в рабочее или глубокой ночью. Примерно в течении часа сервер помирает.

В apache2 error.log начинает ругаться только когда переполняется память и серв не может больше плодить процессы. В других логах так же вроде как чисто.

Я запарился с этим биться уже. Прошу советы в стиле "переустанови виндовс" не давать. Это будет уже самая крайняя стадия, пока что важно найти корень зла, а не вырубать весь лес.

Хочу так же добавить, что раньше был просто nginx + php5-fpm и ситуация была точно такая же, только пладились процессы php5-fpm. (это было хуже, потому что при загрузке в 100% всех ядер работать было не возможно, а при текущей ситуации, плодовитость процессов на скорость работы практически не влияет, пока они не сожрут всю память).

Скажу еще главную фразу: "раньше всё работало отлично в течении нескольких месяцев. никакие настройки я не менял и оно само"

Я пытаюсь настроить веб-сервер на VPS. Моя проблема заключается в том, что использование памяти процессов php-cgi увеличивается со временем, даже несмотря на то, что веб-сайт вообще не получает никакого трафика. (он находится за брандмауэром на данный момент)

Веб-сайт основан на Drupal. Используя модуль Deupal Drupal, я могу сказать, что использование памяти PHP-скриптов в среднем меньше 20 КБ и никогда не превышает 8 МБ.

Вот соответствующие части из вывода ps aux :

  • Нормально ли иметь большой размер php-cgi?
  • Можно ли оценить использование памяти php-cgi на основе настроек?
  • Любые советы по сокращению потребления памяти процессов php-cgi?

Поиск известных ошибок утечки памяти не приносил ничего значимого. И я был бы удивлен, если бы пакет Debian по умолчанию имел такую ​​очевидную утечку памяти. Другие пользователи одного и того же хоста не имеют этой проблемы.

То, что я сделал до сих пор, устанавливается на PHP_FCGI_MAX_REQUESTS на низкое значение, чтобы процессы php-cgi были переработаны быстро. Когда я использую ab для имитации высокой нагрузки, это работает очень хорошо. Процессы быстро умирают, прежде чем они вырастут выше 10 МБ. Тем не менее, при низкой и средней нагрузках все процессы неуклонно растут (из-за балансировки нагрузки), и большинство из них потребляют 28 МБ + одновременно, что ставит мой VPS под угрозу обмена. Обратите внимание, что даже без какого-либо трафика процессы неуклонно растут.

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

Кроме того, суммирование общих номеров RSS для процессов php-cgi дает:

Тем не менее, free -m выводит следующий результат:

  • Я что-то упустил? Почему используемая память (без буферов) ниже общей резидентной памяти процессов php-cgi на хосте?

У меня есть следующие расширения PHP:

php5-CGI php5-общий php5-ротор php5-Г.Д. php5-MySQL php5-XCache

PHP memory_limit установлен в 32M.

Вот моя конфигурация FastCGI:

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

Любая помощь приветствуется. Я пытался устранить эту проблему в течение нескольких дней. У меня закончились идеи.

Читайте также: