Вопрос или проблема
В веб-приложении с Nginx и PHP-FPM я заметил моменты медлительности, и, анализируя логи, нашел это сообщение, которое появляется время от времени:
[19-Nov-2017 19:24:09] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
После некоторых исследований я увеличил значения в конфигурационном файле php.ini, остановил и удалил контейнер php и перестроил его, чтобы установить значение в файл на том томе.
Анализируя конфигурационный файл внутри контейнера, я вижу новые значения, которые я установил, однако сообщение об ошибке о pm.max_children (5) продолжает появляться.
Вот мой docker-compose.yml
version: '2'
services:
pi_web:
build: ./nginx
ports:
- "80:80"
- "443:443"
volumes:
- ../src:/src
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- /etc/letsencrypt:/etc/letsencrypt
pi_php:
build: ./php
volumes:
- ../src:/src
- ./php/config/php.ini:/usr/local/etc/php/php.ini
Вот фрагмент ./php/config/php.ini:
pm = dynamic
pm.max_children = 40
pm.start_servers = 15
pm.min_spare_servers = 15
pm.max_spare_servers = 25
И, если я запущу:
$ docker exec -it docker_pi_php_1 cat /usr/local/etc/php/php.ini
Я вижу те же значения, что и в фрагменте выше.
Путь к конфигурационному файлу внутри контейнера правильный, я выполнил:
$ php --ini
внутри контейнера, и путь есть в списке загруженных конфигурационных файлов.
Я изнурял себя, пытаясь решить эту проблему, но пока не преуспел.
Есть идеи?
Могу ошибаться, но предполагая, что вы используете официальные образы PHP, эти настройки pm должны находиться внутри директории /usr/local/etc/php-fpm.d/
в файле с расширением conf. Согласно документации PHP, эти настройки относятся к FPM и, хотя они используют синтаксис php.ini
, их следует разместить в другом файле, поэтому я полагаю, что ваши настройки pm игнорируются. Этот Dockerfile в PHP помог мне выяснить, где должны находиться эти конф файлы.
Я бы проверил, есть ли файл /usr/local/etc/php-fpm.d/www.conf
в вашем контейнере, где значение max_children
сейчас установлено на 5
. Если это так, я полагаю, вы могли бы изменить свой Dockerfile, чтобы скопировать новый файл www.conf, который устанавливает большее значение для pm.max_children
.
Я считаю более ясным перезаписывать конкретные настройки, используя файл, который идет с официальным php:7.3-fpm
изображением: /usr/local/etc/php-fpm.d/zz-docker.conf
Этот файл завершается чем-то вроде:
[www]
listen = 9000
Таким образом, мы можем просто добавить в него именно то, что нужно установить для пула www.
Например:
# НАСТРОЙКА PHP-FPM КОНФИГУРПЦИЙ (max_children / max_requests)
RUN echo 'pm.max_children = 15' >> /usr/local/etc/php-fpm.d/zz-docker.conf && \
echo 'pm.max_requests = 500' >> /usr/local/etc/php-fpm.d/zz-docker.conf
Я думаю, это проще и понятнее.
Файлы, добавленные в директорию /usr/local/etc/php-fpm.d/
, упоминаемые в некоторых ответах, могут не сработать.
Похоже, конфигурация загружает их перед значениями по умолчанию, и значения по умолчанию перезаписывают их. Пункты назначения определяются в следующих шагах сборки PHP-FPM:
RUN set -eux; \
`# ...` \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
`# ...` \
Вы также можете увидеть их в выводе php -i
.
Одно из решений — создать Dockerfile, который явно перезаписывает значения по умолчанию:
FROM php:8.1-fpm-bookworm AS base
# RUN apt-get update && apt-get upgrade ...
FROM build AS deps
# RUN apt-get update && apt-get install ...
# RUN docker-php-ext-install ... && docker-php-ext-enable ...
FROM deps AS config
# @see https://docs.docker.com/guides/php/develop/
# @see https://github.com/docker-library/docs/tree/master/php#configuration
#
RUN mv -v -- "${PHP_INI_DIR}/php.ini-development" "${PHP_INI_DIR}/php.ini";
# Пользовательские настройки проекта, включая разработку (например, PHP "Xdebug").
#
# @see https://github.com/docker-library/php/blob/bde3d5c08a72f61ed5af7592b1910faed1e4a3f2/8.1/bookworm/fpm/Dockerfile#L132
# @see https://www.php.net/manual/en/function.scandir.php
#
COPY './src/conf.d' '/usr/local/etc/php/conf.d'
# Страница состояния PHP-FPM и Ping.
#
# Мы явно изменяем конфигурацию PHP, так как файлы в `conf.d` для PHP могут не работать - конфигурация может быть перезаписана значениями по умолчанию.
#
# @see https://www.php.net/manual/en/fpm.status.php
#
RUN \
sed -i \
-e 's/^;pm.status_path /pm.status_path /' \
-e 's/^;ping.path /ping.path /' -- \
'/usr/local/etc/php-fpm.d/www.conf';
FROM config AS entry
WORKDIR '/var/www'
Ответ или решение
Как и где настроить pm.max_children
для PHP-FPM с использованием Docker
Если вы столкнулись с сообщением об ошибке server reached pm.max_children setting (5), consider raising it
в вашем приложении на PHP-FPM, это означает, что количество доступных процессов PHP-FPM для обработки запросов достигло предела. Данное ограничение можно настроить, изменив значение параметра pm.max_children
. Поскольку вы используете Docker, следует учитывать особенности конфигурации в контейнерах.
1. Понимание конфигурации PHP-FPM
PHP-FPM (PHP FastCGI Process Manager) имеет свои собственные конфигурационные файлы, которые отличаются от стандартных файлов конфигурации PHP (php.ini). Параметры управления работой пула PHP-FPM, включая pm.max_children
, находятся в файлах конфигурации, расположенных в директории /usr/local/etc/php-fpm.d/
.
2. Настройка Docker контейнера
В вашем docker-compose.yml
, указанные параметры настраиваются в файле php.ini
, однако настройки для pm
должны быть внесены в специальный конфигурационный файл для PHP-FPM. Ниже приведен шаг за шагом процесс настройки.
Шаг 1: Создание кастомного Dockerfile
Создайте файл Dockerfile
для вашего PHP-FPM контейнера, если его еще нет. Пример содержимого:
FROM php:8.1-fpm # Или ваша версия
# Настройка php.ini
COPY ./php/config/php.ini /usr/local/etc/php/php.ini
# Конфигурация пула PHP-FPM
RUN echo 'pm = dynamic' >> /usr/local/etc/php-fpm.d/www.conf && \
echo 'pm.max_children = 40' >> /usr/local/etc/php-fpm.d/www.conf && \
echo 'pm.start_servers = 15' >> /usr/local/etc/php-fpm.d/www.conf && \
echo 'pm.min_spare_servers = 15' >> /usr/local/etc/php-fpm.d/www.conf && \
echo 'pm.max_spare_servers = 25' >> /usr/local/etc/php-fpm.d/www.conf
Шаг 2: Обновление docker-compose.yml
Теперь обновим ваш docker-compose.yml
, чтобы он использовал созданный вами Dockerfile. Пример:
version: '2'
services:
pi_web:
build: ./nginx
ports:
- "80:80"
- "443:443"
volumes:
- ../src:/src
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- /etc/letsencrypt:/etc/letsencrypt
pi_php:
build: ./php
volumes:
- ../src:/src
Шаг 3: Пересобираем контейнер
После внесения изменений необходимо пересобрать контейнер с помощью следующей команды:
docker-compose up --build
3. Проверка настроек
После того как контейнер будет запущен, вы можете проверить настройки PHP-FPM, выполнив команду внутри контейнера:
docker exec -it <container_name> php-fpm -t
Также можно просмотреть измененный файл конфигурации:
docker exec -it <container_name> cat /usr/local/etc/php-fpm.d/www.conf
4. Мониторинг производительности
После изменения pm.max_children
важно monitorить производительность приложения и корректировать настройки в зависимости от нагрузки. Данный параметр зависит от доступной памяти и других ресурсов вашего сервера. If necessary, вы также можете увеличить другие параметры управления, такие как pm.start_servers
, pm.min_spare_servers
и pm.max_spare_servers
, чтобы оптимально настроить обработку запросов.
Заключение
Настройка pm.max_children
для PHP-FPM в Docker представляет собой важный шаг для обеспечения оптимальной производительности веб-приложений. Следуя вышеописанным шагам и рекомендациям, вы сможете успешно настроить этот параметр и улучшить отклик вашего приложения. Не забывайте периодически пересматривать и адаптировать настройки для соответствия изменяющимся условиям работы вашего сервера.