Как стать автором
Обновить
890.8
OTUS
Цифровые навыки от ведущих экспертов

Тюнинг PHP-FPM. Введение

Время на прочтение6 мин
Количество просмотров24K
Автор оригинала: benjamin

БОНУС: в нашем подкасте мы обсудили эту тему с экспертом, членом сообщества PHP программистов: https://share.transistor.fm/s/6a8637ba

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

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

PHP-FPM может использовать один из трех режимов управления процессами:

  • static

  • dynamic

  • ondemand

Сейчас мы подробнее рассмотрим, что представляет собой каждый из них.

Static

Static гарантирует, что обработка пользовательских запросов всегда доступна фиксированному количеству дочерних процессов. Оно устанавливается с помощью pm.max_children. В этом режиме запросам не нужно ждать запуска новых процессов, что делает его самым быстрым подходом.

Предположим, что вы выбрали static конфигурацию с постоянно доступными 10 дочерними процессами, тогда вам нужно настроить ее в /etc/php/7.2/fpm/pool.d/www.conf (при условии, что вы используете дефолтную конфигурацию Debian/Ubuntu для PHP-FPM) следующим образом:

pm = static pm.max_children = 10 

Чтобы проверить результат внесенных изменений запустите pstree -c -H <PHP-FPM process id> -S <PHP-FPM process id> после перезапуска PHP-FPM. Вы увидите, как в примере ниже, что доступно десять процессов.

php-fpm7.2-+-php-fpm7.2 |-php-fpm7.2

|-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 |-php-fpm7.2 `-php-fpm7.2

Dynamic

В этом режиме PHP-FPM динамически регулирует количество доступных дочерних процессов и гарантирует постоянную доступность хотя бы одного из них.

Данная конфигурация задействует пять параметров:

  • pm.max_children: максимальное количество дочерних процессов, которые могут быть запущены.

  • pm.start_servers: количество дочерних процессов, запускаемых на запуске PHP-FPM.

  • pm.min_spare_servers: минимальное количество бездействующих дочерних процессов, которые создает PHP-FPM. Если доступно меньше, чем это число, то создаются другие процессы.

  • pm.max_spare_servers: максимальное количество бездействующих дочерних процессов, которые создает PHP-FPM. Если доступно больше дочерних процессов, чем здесь указано, некоторые из них будут “убиты”.

  • pm.process_idle_timeout: время простоя в секундах, по истечении которого дочерний процесс будет убит.

Теперь самое интересное; как рассчитать значения для каждой настройки? Sebastian Buckpesch, предлагает следующую формулу:

Настройка

Значение

max_children

(Общий объем оперативной памяти - Память используемая для Linux, базы данных и т.д.) / Размер процесса

start_servers

Количество ядер процессора х 4

min_spare_servers

Количество ядер процессора х 2

max_spare_servers

То же, что и для start_servers

Мы также должны установить параметр pm.process_idle_timeout - количество секунд, по истечении которых бездействующий процесс будет убит.

Допустим, у нашего сервера два процессора, каждый по четыре ядра, и 8 ГБ оперативной памяти. Если предположить, что Linux и связанные с ним демоны используют около 2 ГБ (для получения более конкретного значения можно использовать free -hl), то у нас останется около 6192 МБ.

Как узнать, сколько памяти использует каждый процесс? Чтобы вычислить это, есть скрипт Python под названием ps_mem.py. После его запуска с помощью sudo python ps_mem.py | grep php-fpm, вы получите следующий результат:

28.4 MiB +  33.8 MiB =  62.2 MiB    php-fpm7.2 (11) 

Первый столбец - это собственная память. Второй столбец — общая память. Третий столбец — это общий объем используемой оперативной памяти. Четвертый столбец — это наименование процесса.

Исходя из вышеизложенного, понятно, что размер процесса составляет 62,2 МБ. Итак, введя все эти значения в нашу формулу, мы получим следующий результат:

# Round the result up. (8192 - 2000) / 62.2 

Исходя из этого, мы получаем следующие значения для наших настроек:

Настройка

Значение

max_children

100

start_servers

32

min_spare_servers

16

max_spare_servers

32

Мы оставим pm.process_idle_timeout равным значению по умолчанию в 10s. Предположим, что нас устраивают эти настройки. Мы бы выполнили их конфигурацию следующим образом:

pm = dynamic pm.max_children = 100 pm.start_servers = 32 pm.min_spare_servers = 16 pm.max_spare_servers = 32 pm.max_requests = 200 

Для отслеживания количества памяти, которое использует ваше приложение, вы можете регулярно использовать инструменты мониторинга памяти. Для PHP доступно несколько опций, включая php-memprof и Tideways.

ondemand

ondemand заставляет PHP-FPM форкать процессы при получении запросов. Чтобы настроить PHP-FPM для его использования, нам нужно установить pm в режим dynamic и предоставить значения для следующих настроек:

  • max_children

  • process_idle_timeout

  • max_requests

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

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

pm = ondemand pm.max_children = 100 pm.process_idle_timeout = 10s pm.max_requests = 200 

Какая конфигурация подойдет вам?

Если честно, ответ на этот вопрос: «смотреть надо по ситуации», поскольку это всегда зависит от типа приложений, которые вы запускаете. Однако все же есть несколько рекомендаций относительно того, какую конфигурацию выбрать.

Сайт с низким трафиком

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

Сайт с высоким трафиком

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

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

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

В режиме dynamic все может быть не так плохо, все зависит от конфигурации. Однако вы можете в итоге получить конфигурацию, которая по сути копирует static.

Использование нескольких пулов для фронтенда/бэкенда

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

  • Фронтенд, где клиенты могут просматривать и совершать покупки.

  • Бэкенд, где администраторы управляют магазином (например, добавляют/удаляют продукты, категории и теги, а также проверяют рейтинги).

При таком подходе, целесообразно иметь один пул, который обслуживает фронтенд, а другой - бэкенд, и настраивать каждый соответствующим образом.

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

Добавьте в /etc/php/7.2/fpm/pool.d/www.conf следующую конфигурацию:

; frontend [frontend] listen = /var/run/php-fpm-frontend.sock user = www-data group = www-data listen.owner = www-data listen.group = www-data pm = static pm.max_children = 5

; backend [backend] listen = /var/run/php-fpm-backend.sock user = www-data group = www-data listen.owner = www-data listen.group = www-data pm = ondemand pm.max_children = 5 pm.process_idle_timeout = 10s

Это создаст два пула: один для фронтенда, а другой — для бэкенда. Оба имеют одного и того же пользователя и группу, но имеют разные конфигурации менеджера процессов и подключены через разные сокеты.

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

Сохранив это, используйте для вашего NGINX vhost файла следующую конфигурацию:

server {   listen       80;   server_name  test-site.localdomain;   root         /var/www/test-site/public;

  access_log /var/log/nginx/test-site.access.log;   error_log  /var/log/nginx/test-site.error.log error;   index index.php;

  set $fpm_socket "unix:/var/run/php-fpm-frontend.sock";

  if ($uri ~* "^/api/") {       set $fpm_socket "unix:/var/run/php-fpm-backend.sock";   }

  location / {     try_files $uri $uri/ /index.php;

    location ~ .php$ {       fastcgi_split_path_info ^(.+.php)(/.+)$;       fastcgi_pass $fpm_socket;       fastcgi_index index.php;       include fastcgi.conf;       fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;     }   } } 

Это создаст конфигурацию виртуального хоста, которая отправляет запросы в пул фронтенда или бэкенда в зависимости от запрошенной локации. Любые запросы к /api отправляются в пул бэкенда, а все остальные запросы направляются во фронтенд.

В заключение

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


Материал подготовлен в рамках курса «PHP Developer. Professional». Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь.

Теги:
Хабы:
Всего голосов 11: ↑6 и ↓5+1
Комментарии3

Публикации

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS