Кэширование Nginx и fastcgi
proxy_cache_path /home/vagrant/Code/ng-cache levels=1:2 keys_zone=ng_cache:10m max_size=10g inactive=60m; proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504; fastcgi_cache_path /home/vagrant/Code/ngd-cache levels=1:2 keys_zone=ngd_cache:10m inactive=60m; fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale error timeout invalid_header http_500; fastcgi_ignore_headers Cache-Control Expires Set-Cookie; add_header NGINX_FASTCGI_CACHE $upstream_cache_status; server { listen 80; listen 443 ssl http2; server_name nginx-performance.app; root "/home/vagrant/Code/project-nginx/public"; index index.html index.htm index.php; charset utf-8; proxy_cache ng_cache; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/nginx-performance.app-error.log error; sendfile off; client_max_body_size 100m; location ~ .php$ { fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.1-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_intercept_errors off; fastcgi_buffer_size 16k; fastcgi_buffers 4 16k; fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_cache ngd_cache; fastcgi_cache_valid 60m; } location ~ /.ht { deny all; } ssl_certificate /etc/nginx/ssl/nginx-performance.app.crt; ssl_certificate_key /etc/nginx/ssl/nginx-performance.app.key; }
Мы открыли файл виртуального хоста Nginx и добавили приведенные выше настройки. Давайте поясним их.
proxy_cache_path /home/vagrant/Code/ng-cache levels=1:2 keys_zone=ng_cache:10m max_size=10g inactive=60m;
Как объяснялось в статье производительность Apache и Nginx: методы оптимизации, proxy_cache_path используется для кеширования статических ресурсов. Таких как изображения, таблицы стилей, файлы JavaScript. Сам путь должен существовать, поэтому необходимо создать эти директории.
levels означает глубину директорий внутри этого пути/папки.
Keys zone – это имя. Каждый виртуальный хост должен использовать отдельное имя. max_size означает максимальный размер кэша, а inactive — что элементы времени будут храниться в кэше, даже если они не запрашиваются.
После этого времени простоя кэш для ресурса будет снова заполнен.
fastcgi_cache_purge
Это определяет запросы, которые смогут очистить кэш. Nginx (его модуль ngx_http_fastcgi_module) предоставляет полный комплект инструментов для кэширования. Пример использования указанной выше директивы:
fastcgi_cache_path /data/nginx/cache keys_zone=cache_zone:10m; map $request_method $purge_method { PURGE 1; default 0; } server { ... location / { fastcgi_pass backend; fastcgi_cache cache_zone; fastcgi_cache_key $uri; fastcgi_cache_purge $purge_method; } }
В этом случае запрос PURGE REST сможет удалить данные из кэша.
Мы добавили заголовки Nginx к ответам, чтобы можно было узнать, обслуживался ли ресурс из кэша или нет.
add_header NGINX_FASTCGI_CACHE $upstream_cache_status;
Затем можно проанализировать время загрузки нашей страницы, чтобы проверить, что работает, а что нет.
Метод fastcgi_cache_methods полезен для кеширования конкретных методов запроса, таких как POST. GET и HEAD.
Активировав приведенную выше конфигурацию, как для статического, так и для динамического контента, мы запустили Locust. Мы подключили к системе 100 параллельных пользователей. Разница в результатах была поразительной. Того напряжения, в котором раньше находился сервер, уже не ощущалось.
Кэширование Nginx принесло несколько значительных улучшений.
Мы видим, что нам удалось сократить время загрузки страницы. Теперь оно составляет меньше секунды!
Мы также протестировали одну страницу галереи, у которой есть дополнительный «багаж» похожих и новых галерей.
Отчет в файле HAR по этому тесту.
Настройка PHP-FPM для повышения производительности + Low Memory
Откройте файл конфигурации PHP-FPM для PHP 7.0.
sudo nano /etc/php/7.0/fpm/pool.d/www.conf
Настройте следующие значения, как показано ниже, обратите внимание на перед , и. означает, что дочерние процессы в PHP-FPM будут порождаться только при необходимости
означает, что дочерние процессы в PHP-FPM будут порождаться только при необходимости
это максимальное количество дочерних процессов, которые будут разрешены, 50 является достаточно либеральным, но если вы видите в своем архиве журналов что количество дочерних процессов превысило максимальное значение, то необходимо увеличить это значение
убивает дочерние процессы после того, как они бездействовали в течение 10 секунд
устанавливает максимальное количество запросов PHP для каждого дочернего процесса
pm = ondemand ; Число дочерних процессов, которые будет создано, когда pm установлен в 'static' и ; Максимальное число дочерних процессов, когда pm установлен в 'dynamic' и 'ondemand'. ; Это значение устанавливает ограничение на количество одновременных запросов, которые будут ; запускаться. Эквивалент директивы ApacheMaxClients в mpm_prefork. ; Эквивалентная переменная среды PHP_FCGI_CHILDREN в оригинальном PHP ; CGI. Ниже, по умолчанию основаны на сервере без использования значительных ресурсов. Не ; забудьте настройки часов.* чтобы соответствовать вашим потребностям. ; Примечание: используется, когда pm установлен в 'static', 'dynamic' или 'ondemand' ; Примечание: это значение является обязательным. pm.max_children = 50 ; Число дочерних процессов, созданных при запуске. ; Примечание: используется только тогда, когда pm установлен в "dynamic" ; Значение по умолчанию: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 ;pm.start_servers = 2 ; Требуемое минимальное число неактивных процессов сервера. ; Примечание: используется только тогда, когда pm установлен в "dynamic" ; Примечание: обязательное, когда pm установлен в "dynamic" ;pm.min_spare_servers = 1 ; Требуемое максимальное число неактивных процессов сервера. ; Примечание: используется только тогда, когда pm установлен в "dynamic" ; Примечание: обязательное, когда pm установлен в "dynamic" ;pm.max_spare_servers = 3 ; Число секунд, по истечении которых бездействующий процесс будет убит. ; Примечание: используется только тогда, когда pm установлен в 'ondemand' ; Значение по умолчанию: 10s pm.process_idle_timeout = 10s; ; Число запросов после которых дочерний процесс будет перезапущен. ; Это может быть полезно во избежания утечек памяти в 3-й партии библиотек. Для ; бесконечной обработки запроса укажите '0'. Эквивалент PHP_FCGI_MAX_REQUESTS. ; Значение по Умолчанию: 0 pm.max_requests = 500
Проверьте правильность вашего синтаксиса конфигурации PHP-FPM
php-fpm7.0 -t
Вы должны увидеть, что конфигурация действует
NOTICE: configuration file /etc/php/7.0/fpm/php-fpm.conf test is successful
Теперь вы можете перезапустить php7.0-FPM
sudo service php7.0-fpm restart
Вы можете увидеть, что объем оперативной памяти используется значительно меньше.
500 rps
Ссылки с детальным отчетом
- php-fpm https://overload.yandex.net/150705
- php-ppm https://overload.yandex.net/150710
- nginx-unit https://overload.yandex.net/150711
- road-runner https://overload.yandex.net/150715
- road-runner-reboot https://overload.yandex.net/152011
- react-php https://overload.yandex.net/150717
- react-php-reboot https://overload.yandex.net/152064
Перцентили времени ответа
95%(ms) | 90%(ms) | 80%(ms) | 50%(ms) | HTTP OK(%) | HTTP OK(count) | |
---|---|---|---|---|---|---|
php-fpm | 13 | 8.4 | 5.3 | 3.69 | 100 | 285030 |
php-ppm | 15 | 9 | 4.72 | 3.24 | 100 | 285030 |
nginx-unit | 12 | 8 | 5.5 | 3.93 | 100 | 285030 |
road-runner | 9.6 | 6 | 3.71 | 2.83 | 100 | 285030 |
road-runner-reboot | 14 | 11 | 7.1 | 4.45 | 100 | 285030 |
react-php | 9.3 | 5.8 | 3.57 | 2.68 | 100 | 285030 |
react-php-reboot | 15 | 12 | 7.2 | 4.21 | 100 | 285030 |
Мониторинг
cpu median(%) | cpu max(%) | memory median(MB) | memory max(MB) | |
---|---|---|---|---|
php-fpm | 41.68 | 48.33 | 1,006.06 | 1,015.09 |
php-ppm | 33.90 | 48.90 | 1,046.32 | 1,055.00 |
nginx-unit | 42.13 | 47.92 | 1,006.67 | 1,015.73 |
road-runner | 24.08 | 28.06 | 1,035.86 | 1,044.58 |
road-runner-reboot | 46.23 | 52.04 | 939.63 | 948.08 |
react-php | 19.57 | 23.42 | 1,049.83 | 1,060.26 |
react-php-reboot | 41.30 | 47.89 | 957.01 | 958.56 |
Графики
График 2.1 Среднее время ответа в секунду
График 2.2 Средняя нагрузка процессора в секунду
График 2.3 Среднее потребление памяти в секунду
Настройка dynamic пула
Для основного сервера приложения, ввиду явных преимуществ, часто выбирают dynamic пул. Его работа описана следующими настройками:
- pm.max_children — максимальное количество дочерних процессов
- pm.start_servers — количество процессов при старте
- pm.min_spare_servers — минимальное количество процессов, ожидающих соединения (запросов для обработки)
- pm.max_spare_servers — максимальное количество процессов, ожидающих соединения (запросов для обработки)
Для того чтобы корректно установить эти значения, необходимо учитывать:
- сколько памяти в среднем потребляет дочерний процесс
- объем доступного ОЗУ
Выяснить среднее значение памяти на один php-fpm процесс на уже работающем приложении можно с помощью планировщика:
Нам необходимо среднее значение в колонке RSS (размер резидентной памяти в килобайтах). В моем случае это ~20Мб. В случае, если нагрузки на приложения нет, можно использовать Apache Benchmark, для создания простейшей нагрузки на php-fpm.
Объем общей / доступной / используемой памяти можно посмотреть с помощью free:
Далее, возьмем за основу формулу для расчета pm.max_children (источник), и проведем расчет на примере:
Значение остальных директив можно установить исходя из ожидаемой нагрузки на приложение а также учесть чем еще занимается сервер кроме работы php-fpm (скажем СУБД также требует ресурсов). В случае наличия множества задач на сервере — стоит снизить к-во как начальных / максимальных процессов.
К примеру учтем что на сервере находиться 2 пула www1 и www2 (к примеру 2 веб-ресурса), тогда конфигурация каждого из них может выглядеть как:
Recommendation for PHP-FPM monitoring
Note:
- By default the status page output is formatted as
text/plain. Passing either
html,
xml or
json in the query string will return the corresponding - By default the status page only outputs short status. Passing
full in the query string will also return status for each pool process
For example:
http://example.bar/status
http://example.bar/status?json
http://example.bar/status?full
http://example.bar/status?json&full
1 |
http//example.bar/status http//example.bar/status?json http//example.bar/status?full http//example.bar/status?json&full |
Purpose: The URI to view the FPM status pageDefault Value: Not definedConfiguration:
pm.status_path = /status
1 | pm.status_path=/status |
1000 rps
Ссылки с детальным отчетом
- php-fpm https://overload.yandex.net/150841
- php-fpm-80 https://overload.yandex.net/153612
- php-ppm https://overload.yandex.net/150842
- nginx-unit https://overload.yandex.net/150843
- road-runner https://overload.yandex.net/150844
- road-runner-reboot https://overload.yandex.net/152068
- react-php https://overload.yandex.net/150846
- react-php-reboot https://overload.yandex.net/152065
Перцентили времени ответа
95%(ms) | 90%(ms) | 80%(ms) | 50%(ms) | HTTP OK(%) | HTTP OK(count) | |
---|---|---|---|---|---|---|
php-fpm | 11050 | 11050 | 9040 | 195 | 80.67 | 72627 |
php-fpm-80 | 3150 | 1375 | 1165 | 152 | 99.85 | 89895 |
php-ppm | 2785 | 2740 | 2685 | 2545 | 100 | 90030 |
nginx-unit | 98 | 80 | 60 | 21 | 100 | 90030 |
road-runner | 27 | 15 | 7.1 | 3.21 | 100 | 90030 |
road-runner-reboot | 1110 | 1100 | 1085 | 1060 | 100 | 90030 |
react-php | 23 | 13 | 5.6 | 2.86 | 100 | 90030 |
react-php-reboot | 28 | 24 | 19 | 11 | 100 | 90030 |
Мониторинг
cpu median(%) | cpu max(%) | memory median(MB) | memory max(MB) | |
---|---|---|---|---|
php-fpm | 12.66 | 78.25 | 990.16 | 1,006.56 |
php-fpm-80 | 83.78 | 91.28 | 746.01 | 937.24 |
php-ppm | 66.16 | 91.20 | 1,088.74 | 1,102.92 |
nginx-unit | 78.11 | 88.77 | 1,010.15 | 1,062.01 |
road-runner | 42.93 | 54.23 | 1,010.89 | 1,068.48 |
road-runner-reboot | 77.64 | 85.66 | 976.44 | 1,044.05 |
react-php | 36.39 | 46.31 | 1,018.03 | 1,088.23 |
react-php-reboot | 72.11 | 81.81 | 911.28 | 961.62 |
Графики
График 3.1 Среднее время ответа в секунду
График 3.2 Среднее время ответа в секунду (без php-fpm, php-ppm, road-runner-reboot)
График 3.3 Средняя нагрузка процессора в секунду
График 3.4 Среднее потребление памяти в секунду
10000 rps
Ссылки с детальным отчетом
- php-fpm https://overload.yandex.net/150849
- php-fpm-80 https://overload.yandex.net/153615
- php-ppm https://overload.yandex.net/150874
- nginx-unit https://overload.yandex.net/150876
- road-runner https://overload.yandex.net/150881
- road-runner-reboot https://overload.yandex.net/152069
- react-php https://overload.yandex.net/150885
- react-php-reboot https://overload.yandex.net/152066
Перцентили времени ответа
95%(ms) | 90%(ms) | 80%(ms) | 50%(ms) | HTTP OK(%) | HTTP OK(count) | |
---|---|---|---|---|---|---|
php-fpm | 11050 | 11050 | 11050 | 1880 | 70.466 | 317107 |
php-fpm-80 | 3260 | 3140 | 1360 | 1145 | 99.619 | 448301 |
php-ppm | 2755 | 2730 | 2695 | 2605 | 100 | 450015 |
nginx-unit | 1020 | 1010 | 1000 | 980 | 100 | 450015 |
road-runner | 640 | 630 | 615 | 580 | 100 | 450015 |
road-runner-reboot | 1130 | 1120 | 1110 | 1085 | 100 | 450015 |
react-php | 1890 | 1090 | 1045 | 58 | 99.996 | 449996 |
react-php-reboot | 3480 | 3070 | 1255 | 91 | 99.72 | 448753 |
Мониторинг
cpu median(%) | cpu max(%) | memory median(MB) | memory max(MB) | |
---|---|---|---|---|
php-fpm | 5.57 | 79.35 | 984.47 | 998.78 |
php-fpm-80 | 85.05 | 92.19 | 936.64 | 943.93 |
php-ppm | 66.86 | 82.41 | 1,089.31 | 1,097.41 |
nginx-unit | 86.14 | 93.94 | 1,067.71 | 1,069.52 |
road-runner | 73.41 | 82.72 | 1,129.48 | 1,134.00 |
road-runner-reboot | 80.32 | 86.29 | 982.69 | 984.80 |
react-php | 73.76 | 82.18 | 1,101.71 | 1,105.06 |
react-php-reboot | 85.77 | 91.92 | 975.85 | 978.42 |
График 4.1 Среднее время ответа в секунду
График 4.2 Среднее время ответа в секунду (без php-fpm, php-ppm)
График 4.3 Средняя нагрузка процессора в секунду
График 4.4 Среднее потребление памяти в секунду
Ondemand Process Manager
A far better way to run PHP-FPM pools, but badly documented, would be the ‘ondemand’ Process Manager. As the name suggests, it does not leave processes lingering, but spawns them as they are needed. The configuration is similar to the above, but simplified.
... pm = ondemand pm.max_children = 5 pm.process_idle_timeout = 10s pm.max_requests = 200
The ‘ondemand’ process manager was added since PHP 5.3.8. The config above causes your default processlist to look like this.
root 3986 4704 ? Ss 19:04 php-fpm: master process (/etc/php-fpm.conf)
Only the master process is spawned, there are no pre-forked PHP-FPM processes. Only when processes are needed will they be started, to a maximum of 5 (with the config above, which is defined by pm.max_children). So if there are 2 simultaneous PHP requests going on, the processlist would be:
root 3986 4704 ? Ss 19:04 php-fpm: master process (/etc/php-fpm.conf) user 3987 4504 ? S 19:04 \_ php-fpm: pool pool_name user 3987 4504 ? S 19:04 \_ php-fpm: pool pool_name
After the configured timeout in “pm.process_idle_timeout», the process will be stopped again. This does not impact PHP’s max_execution_time, because the process manager only considers a process “idle” when it’s not serving any request.
If you’re working on a high performance PHP setup, the ‘ondemand’ PM may not be for you. In that case, it’s wise to pre-fork your PHP-FPM processes up to the maximum your server can handle. That way, all your processes are ready to serve your requests without needing to be spawned first. However, for 90% of the sites out there, the ondemand PHP-FPM configuration is better than either static or dynamic.
Conclusion
My final thought is that it’s worth tweaking your PHP-FPM settings or at least taking some time to understand where the bottlenecks lie and where you can squeeze every bit of performance with your PHP-FPM configuration.
To figure out whether to use dynamic, static or ondemand, just take a hard look at your server setup and what it’s doing.
If you have a dedicated web server, then I would personally use static.
If you have server that does everything (web/db), dynamic would be a better bet.
If you’re running a really poxy server with little memory and you don’t get much traffic or if your application doesn’t take too long to process PHP code, then I suggest you use ondemand.
When to use pm ‘ondemand’ and ‘dynamic’
Using pm dynamic you may have noticed errors similar to:
WARNING: seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 4 idle, and 59 total children
You may try to increase/adjust settings and still see the same error as someone describes in this Serverfault post . In that case, the pm.min was too low and because web traffic fluctuates greatly with dips and spikes, using pm dynamic can be difficult to tune correctly. The common advice is to use pm ondemand, as is the advice in this same support thread. However, that’s even worse, because ondemand will shutdown idle processes right down to 0 when there’s little to no traffic and then you’ll end up with just as much overhead issues as traffic fluctuates. Unless, of course you set the idle timeout extremely high. In which case you should just be using pm.static + a high pm.max_requests.
However, PM dynamic and especially ondemand can save you when you have multiple PHP-FPM pools. For example, hosting multiple cPanel accounts or multiple websites under different pools. I have a server for example with 100+ cpanel accounts and about 200+ domains and it would be impossible for pm.static or even dynamic to perform well. Only ondemand performs well since more than two third’s of the websites receive little to no traffic and with ondemand it means all children will be shutdown saving tons of server memory! Thankfully, cPanel devs figured this out and now defaults to ondemand. Previously with dynamic as default, it made PHP-FPM not an option on busy shared servers. Many would use suPHP because of pm dynamic eating up memory even on idle cPanel PHP-FPM pools/accounts. Chances are, if you receive good traffic, you won’t be hosted on a server with lots of PHP-FPM pools (shared hosting).
Php Fpm 7.3 On dynamic Settings
pm = dynamic
pm.max_children = 60 (max child process based on memory max memory if 128*60=7680MB in upper limit)
40*128=5120MB if every request uses 128MB memory.
max children value:
pm.start_servers value
; Default Value: min_spare_servers + (max_spare_servers – min_spare_servers) / 2
8+(10-6=4)/2 = 12/2=6
pm.start_servers = 8 (4*number of cores on server =
pm.min_spare_servers = 6 (2*Cpu core =4
pm.max_spare_servers = 10 (4*Cpu cores =8) // Generally idea 2x memory required for cpu cores general tasks.
pm.max_requests = 5000
upgrading
pm.start_servers = 10
pm.min_spare_servers = 12
pm.max_spare_servers = 20
4+(20-4=16)/2=10 (pm.start_servers)
;pm.process_idle_timeout = 10s; //on demand only
Global Directives (php-fpm.conf)
Define emergency_restart_threshold Value
Purpose: If this number of child processes exit with Segmentation, page fault, and access violation (SIGSEGV or SIGBUS) within the time interval set by
emergency_restart_interval then FPM will restartDefault Value: 0 means OffConfiguration:
emergency_restart_threshold = 10
1 | emergency_restart_threshold=10 |
Define emergency_restart_interval Value
Purpose: Interval of time used to determine when a graceful restart will be initiated. This can be useful to work around accidental corruptions in an accelerator’s shared memoryDefault Value: 0Available Units: s(econds), m(inutes), h(ours), or d(ays)Configuration:
emergency_restart_interval = 1m
2 | emergency_restart_interval=1m |
Define process_control_timeout Value
Purpose: Time limit for child processes to wait for a reaction on signals from masterDefault Value:Configuration:
process_control_timeout = 10
3 | process_control_timeout=10 |
You know the Platform, define Events Notification Mechanism for FPM
Purpose: Choosen mechanism used by FPM for events notificationSupported Mechanism(s):
select (any POSIX os)
poll (any POSIX os)
epoll (linux >= 2.5.44)
kqueue (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0)
/dev/poll (Solaris >= 7)
port (Solaris >= 10)
events.mechanism = epoll
4 | events.mechanism=epoll |
php fpm max requests
by deafault 500
Applicable only when using: dynamic
increase upto 5000
Why: process has to kil upon completing 500 or specified requested to avoid memory leakage.
Determining Average memory usage per process
root@instance-1:~# ps –no-headers -o “rss,cmd” -C php-fpm7.4 | awk ‘{ sum+=$1 } END { printf (“%d%s\n”, sum/NR/1024,”M”) }’
283M
root@instance-1:~# systemctl restart php7.4-fpm
root@instance-1:~# ps –no-headers -o “rss,cmd” -C php-fpm7.4 | awk ‘{ sum+=$1 } END { printf (“%d%s\n”, sum/NR/1024,”M”) }’
29M
root@instance-1:~# ps –no-headers -o “rss,cmd” -C php-fpm7.4 | awk ‘{ sum+=$1 } END { printf (“%d%s\n”, sum/NR/1024,”M”) }’
96M
root@instance-1:~# ps -ef | grep ‘’pm
root 216323 1 0 15:48 ? 00:00:00 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf)
www-data 216333 216323 0 15:48 ? 00:00:01 php-fpm: pool www
www-data 216334 216323 0 15:48 ? 00:00:02 php-fpm: pool www
www-data 216335 216323 0 15:48 ? 00:00:01 php-fpm: pool www
www-data 216336 216323 0 15:48 ? 00:00:00 php-fpm: pool www
www-data 216337 216323 0 15:48 ? 00:00:00 php-fpm: pool www
www-data 216338 216323 0 15:48 ? 00:00:02 php-fpm: pool www
www-data 216339 216323 0 15:48 ? 00:00:00 php-fpm: pool www
www-data 216340 216323 0 15:48 ? 00:00:00 php-fpm: pool www
ps -ylC php-fpm –sort:rss
ps -ylC php7.3-fpm –sort:rss
RSS contains the average memory usage in kilobytes per process.
S UID PID PPID C PRI NI RSS SZ WCHAN TTY TIME CMD
S 0 24439 1 0 80 0 6364 57236 – ? 00:00:00 php-fpm
S 33 24701 24439 2 80 0 61588 63335 – ? 00:04:07 php-fpm
S 33 25319 24439 2 80 0 61620 63314 – ? 00:02:35 php-fpm
61588 = 60mb
Looking at the PHP-FPM configuration
Here’s what an abbreviated configuration can look like. You would now have a single .conf file that contains the configuration of your master process (PID etc.) as well as the definition of 1 PHP-FPM pool.
$ cat /etc/php-fpm.d/pool1.conf pid = /var/run/php-fpm/pool1.pid log_level = notice emergency_restart_threshold = 0 emergency_restart_interval = 0 process_control_timeout = 0 daemonize = yes listen = /var/run/php-fpm/pool1.sock listen.owner = pool1 listen.group = pool1 listen.mode = 0666 user = pool1 group = pool1 pm = ondemand pm.max_children = 5 pm.process_idle_timeout = 10s pm.max_requests = 500
The above contains the most important bits; the main config determines that it can be daemonized and where the PID-file should be located. The Pool-configuration has the basic information of where to listen to and the type of Process Manager.
The init.d file is a simple copy/paste from the default /etc/init.d/php-fpm with a few modifications.
$ cat /etc/init.d/php-fpm-pool1 #! /bin/sh # # chkconfig: - 84 16 # description: PHP FastCGI Process Manager for pool 'pool1' # processname: php-fpm-pool1 # config: /etc/php-fpm.d/pool1.conf # pidfile: /var/run/php-fpm/pool1.pid # Standard LSB functions #. /lib/lsb/init-functions # Source function library. . /etc/init.d/functions # Check that networking is up. . /etc/sysconfig/network if then exit 0 fi RETVAL=0 prog="php-fpm-pool1" pidfile=/var/run/php-fpm/pool1.pid lockfile=/var/lock/subsys/php-fpm-pool1 fpmconfig=/etc/php-fpm.d/pool1 start () { echo -n $"Starting $prog: " daemon --pidfile ${pidfile} php-fpm --fpm-config=${fpmconfig} --daemonize RETVAL=$? echo && touch ${lockfile} } stop () { echo -n $"Stopping $prog: " killproc -p ${pidfile} php-fpm RETVAL=$? echo if ; then rm -f ${lockfile} ${pidfile} fi } restart () { stop start } reload () { echo -n $"Reloading $prog: " killproc -p ${pidfile} php-fpm -USR2 RETVAL=$? echo } # See how we were called. case "$1" in start) start ;; stop) stop ;; status) status -p ${pidfile} php-fpm RETVAL=$? ;; restart) restart ;; reload|force-reload) reload ;; condrestart|try-restart) && restart || : ;; *) echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart|try-restart}" RETVAL=2 ;; esac exit $RETVAL
The only pieces we changed to that init.d script are at the top; a new process name has been defined (this needs to be unique) and the PID-file has been changed to point to our custom PID-file for this pool, as it’s defined in the pool1.conf file above.
You can now start/stop this pool separately from all the others. It’s configuration can be changed without impacting others. If you have multiple pools configured, your process list would look like this.
root 5963 4704 ? Ss 19:23 0:00 php-fpm: master process (/etc/php-fpm.d/pool1.conf) root 6036 4744 ? Ss 19:23 0:00 php-fpm: master process (/etc/php-fpm.d/pool2.conf)
Multiple master processes are running as root and are listening to a socket defined in the pool configuration. As soon as PHP requests are made, they spawn children to handle them and stop them again after 10s of idling. The master process also shows which configuration file it loaded, making it easy to pinpoint the configuration of that particular pool.