An unedited version of the article was originally published on haydenjames.io and published here with the permission of its author .
I will briefly tell you how best to configure PHP-FPM to increase throughput, reduce latency, and more consistently use processor resources and memory. The default PM string (process manager, process manager) in PHP-FPM is dynamic , and if you do not have enough memory, it is better to install ondemand . Let's compare 2 management options based on php.net documentation and see how my favorite static pm differs from them for a large amount of traffic:
pm = dynamic - the number of child processes is configured dynamically based on the following directives: pm.max_children, pm.start_servers, pm.min_spare_servers, pm.max_spare_servers .
pm = ondemand - processes are created on demand (as opposed to dynamic creation, when pm.start_servers are started when the service is started).
pm = static - the number of child processes is fixed and specified by the pm.max_children parameter.
See the full list of global php-fpm.conf directives for details .
This may seem offtopic, but I'm going to link this to the topic of PHP-FPM customization. Who has not slowed down the processor at least once - on a laptop, virtual machine or a dedicated server. Remember the CPU frequency scaling? These options, available for nix and Windows, can improve system performance and speed of response if you change the processor regulator parameter from ondemand to performance *. This time, let's compare the descriptions and look at the similarities:
Governor = ondemand - dynamic scaling of the processor frequency depending on the current load. Sharply switches to maximum frequency, and then reduces it when idle periods increase.
Governor = conservative = dynamic frequency scaling depending on the current load. Increases and decreases the frequency smoother than ondemand.
Governor = performance - the frequency is always the maximum.
For details, see the complete list of CPU frequency control parameters .
See the similarities? I wanted to show this comparison to convince you that it is best to use pm static for PHP-FPM.
For a processor controller, the performance parameter helps to safely increase performance, because it depends almost entirely on the server's processor limit. In addition, of course, there are still factors such as temperature, battery charge (in a laptop) and other side effects of a permanent processor operation of 100%. Performance tuning provides the fastest processor performance. Read, for example, about the force_turbo parameter in the Raspberry Pi , with which the RPi panel will use the performance controller, where performance improvements will be more noticeable due to the low CPU clock frequency.
The PHP-FPM pm static parameter is largely dependent on the free memory on the server. If there is little memory, it is better to choose ondemand or dynamic . On the other hand, if you have memory, you can avoid the extra costs of the PHP process manager by setting pm static to the maximum server capacity. In other words, if everything is well calculated, you need to set pm.static to the maximum amount of PHP-FPM processes that can be executed without creating problems with insufficient memory or cache. But not so high to overload the processors and accumulate a bunch of PHP-FPM operations that are waiting to be completed .
In the screenshot above, the server is set to pm = static and pm.max_children = 100 , and it takes about 10 GB out of the available 32. Pay attention to the highlighted columns, here and so everything is clear. This screenshot was about 200 active users (over 60 seconds) in Google Analytics. At this level, approximately 70% of the PHP-FPM child processes are still inactive. This means that PHP-FPM is always set to the maximum amount of server resources, regardless of current traffic. The idle process waits for traffic peaks and responds instantly. You do not have to wait for pm to create child processes, and then complete them when the pm.process_idle_timeout period expires . I set a very great value for pm.max_requests , because it is a working server with no memory leaks in PHP. You can set pm.max_requests = 0 with static, if you are fully confident in the existing and future PHP scripts. But it is better to restart the scripts with time. Set a large number of requests, because we want to avoid the extra costs of pm. For example, at least pm.max_requests = 1000 - depending on the number of pm.max_children and the number of requests per second.
The screenshot shows the Linux top command, filtered by u (user) and the PHP-FPM username. Only the first 50 or so processes are shown (not exactly counted), but, in fact, the top shows the top statistics that fit into the terminal window. In this case, sorted by% CPU (% CPU). To view all 100 PHP-FPM processes, run the command:
top -bn1 | grep php-fpm
If you use pm dynamic , these errors occur:
WARNING: [pool xxxx] 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
Try to change the parameter, the error will not go anywhere, as described in this post on Serverfault . In this case, the value of pm.min was too small, and since the web traffic is changing a lot and it has high peaks and deep drops, it is difficult to adequately configure pm dynamic . Usually this uses pm ondemand , as advised in the same post . But this is even worse, because ondemand terminates inactive processes to zero, when there is little or no traffic, and in the end, you will still suffer with costs when traffic changes. Unless, of course, you have set a huge waiting time. And then it’s better to use pm.static + high pm.max_requests .
PM dynamic and especially ondemand can be useful if you have several PHP-FPM pools. For example, you place several cPanel accounts or several websites in different pools. I have a server where, let's say, 100+ cpanel accounts and about 200 domains, and pm.static or even dynamic wouldn't save me. All that is needed is ondemand , because more than two-thirds of websites receive little or no traffic, and with ondemand all child processes will fall off, which will save us a lot of memory! Fortunately, the cPanel developers noticed this and set the default ondemand . Previously, when the default value was dynamic , PHP-FPM was not at all appropriate for busy shared servers. Many people used suPHP because pm dynamic consumed memory even with idle pools and cPanel PHP-FPM accounts. Most likely, with good traffic, you will not be hosted on a server with a large number of PHP-FPM pools (shared hosting).
If you use PHP-FPM and you have serious traffic, the ondemand and dynamic process managers for PHP-FPM will limit the bandwidth due to their inherent costs. Examine your system and configure the PHP-FPM processes to match the maximum server capacity. First, set pm.max_children depending on the maximum use of pm dynamic or ondemand , and then increase this value to a level where the memory and processor will work without overloading. You will notice that with pm static , since everything is stored in your memory, traffic peaks will cause less peaks for the processor over time, and the average server and processor loads will equalize. The average size of the PHP-FPM process depends on the web server and requires manual configuration; therefore, more automated process managers — dynamic and ondemand — are more popular. Hope the article was helpful.
UPD Added benchmark chart ab . If the PHP-FPM processes are in memory, the performance increases due to the memory consumption where they sit and wait. Find the best option for yourself.
Source: https://habr.com/ru/post/460511/
All Articles