Плагин PHP-FPM

Мониторинг PHP-FPM (FastCGI Process Manager) с подробными метриками по пулам процессов, производительности запросов, медленным запросам и использованию ресурсов.

Обзор

Плагин PHP-FPM собирает подробные метрики со страницы статуса PHP-FPM, в том числе:

  • Статус пула — имя пула, тип менеджера процессов, время запуска
  • Метрики процессов — активные, простаивающие, всего процессов
  • Статистика запросов — принятые соединения, частота запросов, медленные запросы
  • Метрики очереди — длина очереди прослушивания, максимальная очередь прослушивания
  • Жизненный цикл процессов — достижение лимита дочерних процессов, лимиты процессов
  • Производительность — запросов на процесс, средняя длительность запроса

Требования

Версия PHP-FPM

  • Минимум: PHP 7.4
  • Рекомендуется: PHP 8.1 или новее
  • Протестировано с: PHP 7.4, 8.0, 8.1, 8.2, 8.3

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

Страница статуса должна быть включена в конфигурации пула PHP-FPM.

Зависимости Python

Дополнительные пакеты Python не требуются — используется стандартная библиотека urllib.

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

Базовая конфигурация

plugins:
  php_fpm:
    enabled: true
    status_url: http://127.0.0.1:9000/status?json

С пользовательским сокетом

plugins:
  php_fpm:
    enabled: true
    status_url: http://unix:/run/php/php8.1-fpm.sock:/status?json

HTTP через Nginx/Apache

plugins:
  php_fpm:
    enabled: true
    status_url: http://127.0.0.1:8080/fpm-status?json

Все параметры конфигурации

plugins:
  php_fpm:
    enabled: true                               # Enable/disable plugin
    status_url: http://127.0.0.1/status?json    # Status URL
    timeout: 10                                 # Request timeout (seconds)
    format: json                                # Response format (json/text)

Переменные окружения

Конфигурацию можно переопределить с помощью переменных окружения:

export PHP_FPM_STATUS_URL="http://127.0.0.1:8080/status?json"

Настройка PHP-FPM

Включение страницы статуса

Отредактируйте конфигурацию пула PHP-FPM:

Ubuntu/Debian:

sudo nano /etc/php/8.1/fpm/pool.d/www.conf

CentOS/RHEL:

sudo nano /etc/php-fpm.d/www.conf

Включите страницу статуса:

; Enable status page
pm.status_path = /status

Опционально — включите страницу ping:

; Enable ping endpoint
ping.path = /ping
ping.response = pong

Перезапустите PHP-FPM:

# Ubuntu/Debian
sudo systemctl restart php8.1-fpm

# CentOS/RHEL
sudo systemctl restart php-fpm

Конфигурация Nginx

Способ 1: FastCGI через сокет

server {
    listen 127.0.0.1:8080;

    location ~ ^/(status|ping)$ {
        access_log off;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

        # Security: only allow from localhost
        allow 127.0.0.1;
        deny all;
    }
}

Способ 2: FastCGI через TCP

server {
    listen 127.0.0.1:8080;

    location ~ ^/(status|ping)$ {
        access_log off;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Перезагрузите Nginx:

sudo nginx -t && sudo systemctl reload nginx

Конфигурация Apache

Включите mod_proxy_fcgi:

sudo a2enmod proxy_fcgi
sudo systemctl restart apache2

Настройте эндпоинт статуса:

<VirtualHost 127.0.0.1:8080>
    <LocationMatch "^/(status|ping)$">
        ProxyPass "unix:/run/php/php8.1-fpm.sock|fcgi://localhost/"
        Require local
    </LocationMatch>
</VirtualHost>

Соображения безопасности

Ограничьте доступ только localhost:

Nginx:

location /status {
    allow 127.0.0.1;
    allow ::1;
    deny all;

    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    include fastcgi_params;
}

Apache:

<Location /status>
    Require local
</Location>

Конфигурация пула PHP-FPM:

; Restrict allowed clients (if using TCP)
listen.allowed_clients = 127.0.0.1

Собираемые метрики

Метрика Описание Единица Тип
pool Имя пула (например, "www") Строка Info
process_manager Тип PM (static/dynamic/ondemand) Строка Info
start_time Временная метка запуска пула Unix time Gauge
uptime_seconds Секунд с момента запуска Секунды Gauge
accepted_connections Всего принятых соединений Количество Counter
listen_queue Текущая длина очереди прослушивания Количество Gauge
max_listen_queue Максимальная очередь прослушивания с момента запуска Количество Gauge
listen_queue_length Лимит размера очереди прослушивания Количество Gauge
idle_processes Простаивающие процессы Количество Gauge
active_processes Активные процессы Количество Gauge
total_processes Всего процессов Количество Gauge
max_active_processes Максимум активных с момента запуска Количество Gauge
max_children_reached Сколько раз достигнут лимит дочерних процессов Количество Counter
slow_requests Число медленных запросов Количество Counter

Метрики на дашборде

Дашборд StatusRadar отображает:

Карточка обзора

  • Active Processes — текущие активные воркеры
  • Idle Processes — доступные воркеры
  • Listen Queue — запросы в очереди
  • Slow Requests — проблемы производительности

График пула процессов

  • Всего процессов во времени
  • Активные против простаивающих процессов
  • Эффективность менеджера процессов

График метрик очереди

  • Длина очереди прослушивания
  • Максимальная достигнутая очередь
  • Насыщение очереди

График частоты запросов

  • Частота принятых соединений
  • Запросов на процесс
  • Частота медленных запросов

График лимита процессов

  • События достижения лимита дочерних процессов
  • Насыщение пула процессов
  • Планирование ёмкости

Установка

Быстрая установка

PLUGINS='php_fpm' \
TOKEN='your-agent-token' \
PHP_FPM_STATUS_URL='http://127.0.0.1:8080/status?json' \
bash -c "$(curl -sL https://statusradar.dev/install-agent.sh)"

Установка на существующий агент

  1. Включите статус PHP-FPM (см. «Настройка PHP-FPM» выше)

  2. Настройте агент:

    sudo nano /opt/statusradar/config/agent.yaml

    Добавьте:

    plugins:
      php_fpm:
        enabled: true
        status_url: http://127.0.0.1:8080/status?json
  3. Перезапустите агент:

    sudo systemctl restart statusradar-agent
  4. Проверьте:

    sudo journalctl -u statusradar-agent -n 50 --no-pager | grep php_fpm

    Ожидается:

    INFO: Plugin php_fpm: Metrics collected successfully
    INFO: Plugin php_fpm: Pool www, 5 active, 10 idle processes

Тестирование

Ручной тест плагина

cd /opt/statusradar
python3 plugins/php_fpm_plugin.py

Ожидаемый вывод:

Plugin: php_fpm
Enabled: True
Available: True

Collecting metrics...
{
  "pool": "www",
  "process_manager": "dynamic",
  "start_time": 1697457600,
  "uptime_seconds": 86400,
  "accepted_connections": 123456,
  "listen_queue": 0,
  "max_listen_queue": 5,
  "listen_queue_length": 128,
  "idle_processes": 10,
  "active_processes": 5,
  "total_processes": 15,
  "max_active_processes": 12,
  "max_children_reached": 2,
  "slow_requests": 15
}

Проверка эндпоинта статуса

Формат JSON (рекомендуется):

curl http://127.0.0.1:8080/status?json

Текстовый формат:

curl http://127.0.0.1:8080/status?full

Полный список процессов:

curl http://127.0.0.1:8080/status?full&json

Проверка эндпоинта ping

curl http://127.0.0.1:8080/ping

# Expected: pong

Устранение неполадок

Плагин не собирает метрики

Проверка 1: Запущен ли PHP-FPM?

sudo systemctl status php8.1-fpm  # Ubuntu/Debian
sudo systemctl status php-fpm     # CentOS/RHEL

Проверка 2: Включена ли страница статуса?

# Check pool configuration
grep "pm.status_path" /etc/php/8.1/fpm/pool.d/www.conf

# Should show: pm.status_path = /status

Проверка 3: Доступен ли эндпоинт статуса?

curl http://127.0.0.1:8080/status?json

# If connection refused, check Nginx/Apache config
# If 404, PHP-FPM status not enabled

Проверка 4: Проверьте логи агента

sudo journalctl -u statusradar-agent -n 100 --no-pager | grep php_fpm

Распространённые ошибки

"Connection refused"

Ошибка:

ERROR: Plugin php_fpm: Connection refused

Причины:

  1. Nginx/Apache не настроен
  2. Неверный status_url
  3. PHP-FPM не слушает ожидаемый сокет/порт

Решение:

# Check PHP-FPM socket
sudo ls -la /run/php/

# Check Nginx is running
sudo systemctl status nginx

# Test status URL manually
curl -v http://127.0.0.1:8080/status?json

"404 Not Found"

Ошибка:

ERROR: Plugin php_fpm: HTTP 404 - status page not found

Причины:

  1. pm.status_path не установлен в конфигурации пула
  2. Nginx/Apache не настроен на передачу запросов статуса
  3. Неверный путь URL

Решение:

1. Включите в пуле PHP-FPM:

pm.status_path = /status

2. Настройте Nginx:

location /status {
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    include fastcgi_params;
}

3. Перезапустите сервисы:

sudo systemctl restart php8.1-fpm nginx

"Access denied"

Ошибка:

ERROR: Plugin php_fpm: HTTP 403 - Access forbidden

Причина: Ограничения по IP блокируют доступ

Решение:

location /status {
    allow 127.0.0.1;
    allow ::1;
    deny all;

    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    include fastcgi_params;
}

"Invalid JSON response"

Ошибка:

ERROR: Plugin php_fpm: Cannot parse JSON response

Причина: Отсутствует параметр ?json в URL

Решение:

plugins:
  php_fpm:
    status_url: http://127.0.0.1:8080/status?json  # Add ?json

Влияние на производительность

На PHP-FPM

Минимальное влияние:

  • Эндпоинт статуса возвращает предварительно рассчитанную статистику
  • Нет выполнения PHP-скриптов
  • Время отклика: < 1 мс

Бенчмарк:

  • Накладные расходы: < 0.001% CPU
  • Нет измеримой деградации производительности

На агент

Использование ресурсов:

  • Память: +8 МБ
  • CPU: +2% во время сбора
  • Сеть: +1 КБ за сбор

Время сбора: < 0.1 секунды

Сценарии использования

1. Мониторинг пула процессов

Отслеживайте:

  • Активные против простаивающих процессов
  • Насыщение пула процессов
  • Эффективность менеджера процессов

Оповещение при:

  • Активных процессах > 90% от максимума
  • Отсутствии простаивающих процессов (насыщение)
  • Частом достижении лимита дочерних процессов

2. Насыщение очереди

Отслеживайте:

  • Длину очереди прослушивания
  • Максимальную достигнутую очередь прослушивания
  • Очередь против лимита очереди

Оповещение при:

  • Очереди прослушивания > 0 (накапливается backlog)
  • Достижении максимального размера очереди
  • Очереди, приближающейся к лимиту

3. Обнаружение медленных запросов

Отслеживайте:

  • Число медленных запросов
  • Частоту медленных запросов
  • Порог медленных запросов

Оповещение при:

  • Росте числа медленных запросов
  • Частоте медленных запросов > 1% от общего числа

4. Планирование ёмкости

Отслеживайте:

  • Тренд максимума активных процессов
  • Число достижений лимита дочерних процессов
  • Частоту обновления процессов

Используйте для:

  • Определения оптимального pm.max_children
  • Решений по масштабированию
  • Тонкой настройки производительности

Лучшие практики

1. Выберите правильный менеджер процессов

Static PM:

pm = static
pm.max_children = 50
  • Плюсы: Предсказуемое использование ресурсов
  • Минусы: Всегда использует максимум памяти
  • Лучше всего для: Выделенных PHP-серверов, постоянной нагрузки

Dynamic PM (рекомендуется):

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
  • Плюсы: Адаптируется к нагрузке, эффективное использование памяти
  • Минусы: Небольшая задержка при запуске
  • Лучше всего для: Переменной нагрузки, общих серверов

Ondemand PM:

pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10s
  • Плюсы: Минимум памяти при простое
  • Минусы: Медленный первый отклик
  • Лучше всего для: Сайтов с низким трафиком, разработки

2. Рассчитайте pm.max_children

Формула:

pm.max_children = (Available RAM) / (Average PHP process size)

Example:
Available RAM: 2GB = 2048MB
PHP process: 50MB (check with: ps aux | grep php-fpm)
pm.max_children = 2048 / 50 = 40

Всегда оставляйте запас:

Recommended: 80% of calculated value
pm.max_children = 40 × 0.8 = 32

3. Настройте параметры Dynamic PM

Start Servers:

pm.start_servers = (min_spare + max_spare) / 2

Min/Max Spare:

pm.min_spare_servers = pm.max_children × 0.1
pm.max_spare_servers = pm.max_children × 0.2

Пример для pm.max_children = 50:

pm.start_servers = 8
pm.min_spare_servers = 5
pm.max_spare_servers = 10

4. Включите логирование медленных запросов

; Log slow requests
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s

Отслеживайте slow.log на предмет узких мест:

sudo tail -f /var/log/php-fpm/slow.log

5. Установите лимиты запросов

; Terminate long-running requests
request_terminate_timeout = 30s

; Restart workers after N requests (prevent memory leaks)
pm.max_requests = 500

6. Регулярно отслеживайте страницу статуса

Настройте оповещения для:

  • listen_queue > 0 (backlog)
  • max_children_reached > 0 (насыщение)
  • роста slow_requests
  • idle_processes < 2 (нет ёмкости)

Тонкая настройка производительности PHP-FPM

Оптимизация менеджера процессов

Для высокого трафика:

pm = static
pm.max_children = 100

Для переменного трафика:

pm = dynamic
pm.max_children = 50
pm.min_spare_servers = 10
pm.max_spare_servers = 20

Оптимизация обработки запросов

Отключите лог доступа (эндпоинт статуса):

location /status {
    access_log off;  # Reduce I/O
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

Включите OPcache:

opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2

Оптимизация памяти

Уменьшите memory_limit, если возможно:

memory_limit = 128M  # Adjust based on needs

Отслеживайте фактическое использование:

ps aux | grep php-fpm | awk '{sum+=$6} END {print sum/1024 " MB"}'

Расширенная конфигурация

Несколько пулов PHP-FPM

Мониторинг нескольких пулов:

plugins:
  php_fpm_www:
    enabled: true
    status_url: http://127.0.0.1:8080/status?json

  php_fpm_api:
    enabled: true
    status_url: http://127.0.0.1:8081/api-status?json

Настройте разные пулы:

; /etc/php/8.1/fpm/pool.d/www.conf
[www]
pm.status_path = /status

; /etc/php/8.1/fpm/pool.d/api.conf
[api]
pm.status_path = /api-status

Мониторинг через Unix-сокет

Прямой доступ к сокету:

plugins:
  php_fpm:
    enabled: true
    status_url: http://unix:/run/php/php8.1-fpm.sock:/status?json

Примечание: Требуется поддержка Unix-сокетов в HTTP-клиенте (поддерживают не все клиенты).

Docker-контейнер

Мониторинг PHP-FPM в Docker:

plugins:
  php_fpm:
    enabled: true
    status_url: http://php-fpm:9000/status?json

Откройте статус через TCP:

; PHP-FPM config in Docker
listen = 0.0.0.0:9000
pm.status_path = /status

Примеры конфигураций

Nginx + сокет PHP-FPM

plugins:
  php_fpm:
    enabled: true
    status_url: http://127.0.0.1:8080/status?json

Конфигурация Nginx:

server {
    listen 127.0.0.1:8080;

    location /status {
        access_log off;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        allow 127.0.0.1;
        deny all;
    }
}

Apache + PHP-FPM

plugins:
  php_fpm:
    enabled: true
    status_url: http://127.0.0.1:8080/fpm-status?json

Конфигурация Apache:

<VirtualHost 127.0.0.1:8080>
    <Location /fpm-status>
        ProxyPass "unix:/run/php/php8.1-fpm.sock|fcgi://localhost/"
        Require local
    </Location>
</VirtualHost>

Несколько версий PHP

plugins:
  php74:
    enabled: true
    status_url: http://127.0.0.1:8074/status?json

  php81:
    enabled: true
    status_url: http://127.0.0.1:8081/status?json

Ограничения

Текущие ограничения

  1. Нет деталей по отдельным запросам — только общая статистика пула
  2. Нет памяти по процессам — используйте полный статус для подробных метрик
  3. Нет метрик OPcache — отслеживайте отдельно через PHP-скрипт

Масштабируемость

Протестировано с:

  • Пулами с 200+ процессами
  • Обработкой 10 000+ req/sec
  • Несколькими пулами на сервер

Производительность:

  • Отклик эндпоинта статуса постоянен независимо от размера пула
  • Нет влияния на производительность PHP-FPM

Следующие шаги

On this page