PHP повсюду и, возможно, является наиболее распространенным языком в Интернете..


Тем не менее, он не совсем известен своими высокопроизводительными возможностями, особенно когда речь идет о высоко параллельных системах. Вот почему для таких специализированных случаев использования такие языки, как Node (да, я знаю, это не язык), Go и Elixir, берут на себя.

Тем не менее, есть много, что вы можете сделать, чтобы улучшить производительность PHP на вашем сервере. Эта статья посвящена аспектам php-fpm, которые являются естественным способом настройки на вашем сервере, если вы используете Nginx.

Если вы знаете, что такое php-fpm, не стесняйтесь перейти к разделу по оптимизации.

Что такое php-fpm?

Не многие разработчики заинтересованы в DevOps стороны вещей, и даже среди тех, кто это делает, очень немногие знают, что происходит под капотом. Интересно, что когда браузер отправляет запрос на сервер под управлением PHP, это не PHP, который формирует точку первого контакта; вместо этого это HTTP-сервер, основными из которых являются Apache и Nginx. Затем эти «веб-серверы» должны решить, как подключиться к PHP, и передать ему тип запроса, данные и заголовки..

Цикл запрос-ответ в случае PHP (Изображение предоставлено: ProinerTech)

В современных PHP-приложениях приведенная выше часть «поиск файла» представляет собой index.php, который сервер настроен для делегирования всех запросов.

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

Таким образом, при получении запроса сервер запускает новый процесс, который автоматически включает PHP, и выполняет его. Этот метод был назван mod_php, сокращенно «php как модуль». У этого подхода были свои ограничения, которые Nginx преодолел с помощью php-fpm..

В php-fpm ответственность за управление PHP-процессами лежит на PHP-программе внутри сервера. Другими словами, веб-сервер (в нашем случае Nginx) не заботится о том, где находится PHP и как он загружается, если он знает, как отправлять и получать данные с него. Если вы хотите, вы можете рассматривать PHP в этом случае как отдельный сервер, который управляет некоторыми дочерними процессами PHP для входящих запросов (поэтому у нас есть запрос, достигающий сервера, который был получен сервером и передан на сервер). – довольно сумасшедший! :-P).

Если вы выполнили какие-либо настройки Nginx или даже просто вошли в них, вы столкнетесь с чем-то вроде этого:

location ~ \ .php $ {
try_files $ uri = 404;
fastcgi_split_path_info ^ (. + \. php) (/.+) $;
fastcgi_pass unix: /run/php/php7.2-fpm.sock;
fastcgi_index index.php;
включить fastcgi_params;
fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name;
}

Интересующая нас строка выглядит так: fastcgi_pass unix: /run/php/php7.2-fpm.sock ;, который сообщает Nginx об обмене данными с процессом PHP через сокет с именем php7.2-fpm.sock. Таким образом, для каждого входящего запроса Nginx записывает данные через этот файл и, получив выходные данные, отправляет их обратно в браузер..

Еще раз, я должен подчеркнуть, что это не самая полная или самая точная картина того, что происходит, но она полностью точна для большинства задач DevOps.

С учетом этого давайте вспомним то, что мы узнали до сих пор:

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

Или графически:

Как PHP и Nginx работают вместе (Изображение предоставлено DataDog)

Отлично, но сейчас возникает вопрос на миллион долларов: что такое PHP-FPM??

Часть «FPM» в PHP означает «Fast Process Manager», это просто причудливый способ сказать, что PHP, работающий на сервере, – это не отдельный процесс, а некоторые процессы PHP, которые создаются, контролируются и уничтожаются. от этого диспетчера процессов FPM. Именно этот менеджер процессов передает запросы веб-серверу.

PHP-FPM – это целая кроличья нора сама по себе, так что не стесняйтесь исследовать ее, если хотите, но для наших целей это объяснение поможет. ��

Зачем оптимизировать php-fpm?

Так зачем беспокоиться обо всем этом танце, когда все работает хорошо? Почему бы просто не оставить вещи такими, какие они есть?.

По иронии судьбы, это именно тот совет, который я даю для большинства случаев использования. Если ваша установка работает нормально и не имеет особых случаев использования, используйте значения по умолчанию. Однако, если вы хотите масштабировать за пределы одной машины, то выжимать максимум из одной необходимо, так как это может сократить счета сервера в два раза (или даже больше!).

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

Итак, со всем этим давайте посмотрим, что именно мы изменим, пытаясь оптимизировать php-fpm..

Как оптимизировать PHP-FPM?

Расположение файла конфигурации для php-fpm может отличаться на сервере, поэтому вам нужно провести некоторое исследование, чтобы найти его. Вы можете использовать команду find if в UNIX. В моем Ubuntu путь это /etc/php/7.2/fpm/php-fpm.conf. 7.2 – это, конечно, версия PHP, которую я использую.

Вот как выглядят первые несколько строк этого файла:

;;;;;;;;;;;;;;;;;;;;;
; Конфигурация FPM;
;;;;;;;;;;;;;;;;;;;;;

; Все относительные пути в этом файле конфигурации относятся к установке PHP
; префикс (/ usr). Этот префикс может быть динамически изменен с помощью
; аргумент ‘-p’ из командной строки.

;;;;;;;;;;;;;;;;;;
; Глобальные параметры;
;;;;;;;;;;;;;;;;;;

[Глобальный]
; Пид файл
; Примечание: префикс по умолчанию – / var
; Значение по умолчанию: нет
pid = /run/php/php7.2-fpm.pid

; Файл журнала ошибок
; Если установлено "системный журнал", журнал отправляется в syslogd вместо записи
; в локальный файл.
; Примечание: префикс по умолчанию – / var
; Значение по умолчанию: log / php-fpm.log
error_log = /var/log/php7.2-fpm.log

Несколько вещей должны быть сразу очевидны: строка pid = /run/php/php7.2-fpm.pid сообщает нам, какой файл содержит идентификатор процесса php-fpm.

Мы также видим, что /var/log/php7.2-fpm.log – это место, где php-fpm будет хранить свои логи..

Внутри этого файла добавьте еще три переменные, подобные этой:

экстренный_рестарт_порог
аварийный_рестарт_интервал 1м
process_control_timeout 10s

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

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

Третья опция, process_control_timeout, сообщает дочерним процессам, что нужно ждать столько времени, прежде чем выполнить сигнал, полученный от родительского процесса. Это полезно в тех случаях, когда дочерние процессы находятся в середине чего-либо, когда родительские процессы отправляют, например, сигнал KILL. С десятью секундами у них будет больше шансов закончить свои задачи и выйти изящно.

Удивительно, но это не главное в конфигурации php-fpm! Это потому, что для обслуживания веб-запросов php-fpm создает новый пул процессов, который будет иметь отдельную конфигурацию. В моем случае имя пула оказалось www, а файл, который я хотел отредактировать, был /etc/php/7.2/fpm/pool.d/www.conf..

Давайте посмотрим, как начинается этот файл:

; Создать новый пул с именем «www».
; переменная $ pool может использоваться в любой директиве и будет заменена на
; название пула (здесь www)
[WWW]

; По префиксу пула
; Это относится только к следующим директивам:
; – «access.log»
; – «медленный журнал»
; – «слушай» (unixsocket)
; – “chroot”
; – “чдир”
; – ‘php_values’
; – ‘php_admin_values’
; Если не задано, вместо него применяется глобальный префикс (или / usr).
; Примечание. Эта директива также может относиться к глобальному префиксу..
; Значение по умолчанию: нет
; prefix = / path / to / pools / $ pool

; Unix пользователь / группа процессов
; Примечание: пользователь обязателен. Если группа не установлена, группа пользователей по умолчанию
; будет использоваться.
пользователь = www-данные
группа = www-данные

Беглый взгляд на конец фрагмента, приведенного выше, решает загадку, почему процесс сервера выполняется как www-данные. Если при настройке веб-сайта у вас возникли проблемы с правами доступа к файлам, вы, вероятно, сменили владельца или группу каталога на www-data, что позволило процессу PHP записывать файлы журналов, загружать документы и т. Д..

Наконец, мы приходим к источнику вопроса, настройке диспетчера процессов (pm). Как правило, значения по умолчанию будут выглядеть примерно так:

pm = динамический
pm.max_children = 5
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 200

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

; Выберите, как менеджер процессов будет контролировать количество дочерних процессов.
; Возможные значения:
; static – фиксированное число (pm.max_children) дочерних процессов;
; динамический – число дочерних процессов устанавливается динамически на основе
; следующие директивы. С этим процессом управления, будет
; всегда минимум 1 ребенок.
; pm.max_children – максимальное количество детей, которые могут
; быть живым в то же время.
; pm.start_servers – количество детей, созданных при запуске.
; pm.min_spare_servers – минимальное количество детей в режиме ожидания
; состояние (ожидает обработки). Если номер
; «холостых» процессов меньше, чем это
; номер, то некоторые дети будут созданы.
; pm.max_spare_servers – максимальное количество детей в режиме ожидания
; состояние (ожидает обработки). Если номер
; «холостых» процессов больше, чем это
; номер, то некоторые дети будут убиты.
; ondemand – дочерние элементы не создаются при запуске. Дети будут разветвлены, когда
; новые запросы будут подключаться. Используются следующие параметры:
; pm.max_children – максимальное количество детей, которые
; может быть живым одновременно.
; pm.process_idle_timeout – количество секунд, после которого
; пустой процесс будет убит.
; Примечание: это значение обязательно.

Итак, мы видим, что есть три возможных значения:

  • статический: Фиксированное число процессов PHP будет поддерживаться независимо от того, что.
  • динамический: Мы можем указать минимальное и максимальное количество процессов, которые php-fpm будет поддерживать в любой момент времени.
  • по требованию: Процессы создаются и уничтожаются, ну по требованию.

Итак, как эти настройки имеют значение?

Проще говоря, если у вас есть веб-сайт с небольшим трафиком, настройка «динамический» является большей частью пустой тратой ресурсов. Предполагая, что для pm.min_spare_servers установлено значение 3, будут созданы и поддерживаться три PHP-процесса, даже если на сайте отсутствует трафик. В таких случаях «ondemand» является лучшим вариантом, позволяя системе решать, когда запускать новые процессы..

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

Использование pm = static фиксирует число дочерних процессов, позволяя использовать максимум системных ресурсов для обслуживания запросов, а не для управления PHP. Если вы идете по этому пути, знайте, что у него есть свои рекомендации и подводные камни. Довольно плотная, но очень полезная статья об этом Вот.

Заключительные слова

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

Даже если вы знаете все настройки php-fpm наизусть, успех не гарантирован. Если вы понятия не имели о существовании php-fpm, вам не нужно тратить время на беспокойство по этому поводу. Просто продолжайте делать то, что вы уже делаете, и продолжайте.

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

Если вы не готовы тратить время на оптимизацию своих серверов PHP, то вы можете рассмотреть возможность использования надежной платформы, такой как Kinsta кто заботится об оптимизации производительности и безопасности.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me