PHP-FPM is PHP FastCGI Process Manager. It is a FastCGI daemon that allows a website to handle high load. But sometimes this service itself causes high load.
To fix the problem, the first thing to do is check the PHP-FPM error logs, which is available in a location such as
/var/log/php7.4-fpm.log
The location for the error logs varies based on the installation path and PHP version. While checking the error log, we found some warnings like these.
[12-Nov-2018 11:12:11] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 9 idle, and 89 total children
This message means that the PHP-FPM pool is very busy and is unable to handle the high traffic with the existing configuration parameters.
PHP-FPM can lead to high server load due to many reasons:
The first thing server owners tend to do for an immediate fix, is to restart the PHP-FPM service. But simply restarting the service is only a band-aid solution, and you will soon see the load spiking.
When we debug such load issues, we analyze the logs and server performance over a period of time. This helps us to pinpoint the culprit and take prompt actions to fix it.
Switch process manager
Process manager is mainly of 3 types – dynamic, ondemand and static. The performance of the service drastically varies based on this type.
In dynamic type, the number of child processes is set dynamically based on the PHP-FPM parameters in conf file. But it is a bit memory-intensive type.
In static type, the number of child processes is fixed by pm.max_children parameter, but this type is not flexible for a server with changing web traffic. It also consumes too much memory.
In ondemand type, the PHP-FPM processes are spawned only on demand, based on the traffic. This type helps to manage varying traffic in memory restrained servers. But the overhead increases when there is so much traffic fluctuation.
The PHP-FPM process manager is determined after assessing the available server memory, traffic spikes, website pages, CPU usage, etc.
Tweak PHP-FPM parameters
PHP-FPM has a lot of configuration parameters which determine the way it performs. These parameters have to be determined based on available server resources such as RAM and CPU.
For instance, the total processes that run in a server would be approximately = (Total RAM / Memory per process) . In a server with multiple services, all of them are taken into account for the tuning process.
The PHP-FPM configuration file will be available at /etc/php-fpm.conf or some other location based on the service path. The contents of the file would look like:
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 5
pm.max_requests = 150
Some of the major parameters that we tune for performance are:
A common mistake server owners do, is to set very high values for these parameters, to get maximum performance. But if there are not enough resources, such high values can crash the server.
The value for ‘pm.max_children’ parameter is first determined based on the server resources, website traffic and content of the sites. Other parameters are then derived upon further testing.
Enable slow log
In cases where the parameters are fine, but a certain application or site is suspected to cause the high load, we enable the slow log option in PHP-FPM.
request_slowlog_timeout = 6s
slowlog = /var/log/php-fpm/slowlog-site.log
The log file mentioned for ‘slowlog’ parameter in the PHP-FPM config file records the requests that take more than 6 seconds to execute.
Analyzing these requests enable us to track and fix the resource-intensive requests and applications in the server.
Managing multiple pools
PHP-FPM has the option to configure multiple resource pools for separate applications. This helps to contain resources per application and for additional security.
By configuring parameters based on the pool, we restrict a single pool from using up all server resources. Unused pools are deleted for further management.
Tweaking PHP-FPM for best performance, is not just a template fix. The configuration and parameters for the service would vary based on the server needs and resources.
During peak traffic, the performance would be different from that of normal hours. So, after doing the tweaks, we conduct stress tests to see how the service performs during high load.
Based on the server performance during stress test, we do further fine-tuning of the service. We also monitor the server load for a period of time, to ensure that the changes has indeed helped.
In this scenario, we were able to reduce the server load drastically, by performing the PHP-FPM tweaks.
But PHP-FPM tuning alone may not help in certain scenarios where services such as MySQL or web server too are culprits. In those cases, we perform additional tasks such as: