A master process supports multiple pools. Each pool is monitored by the master process on different ports. There are multiple worker processes in the pool.
Each worker process has a built-in PHP interpreter, and the process resides in the background, supporting Prefork is dynamically added.
Each worker process supports compiling scripts at runtime and caching the generated opcode in memory to improve performance.
Each worker process supports configuring automatic restart after responding to a specified number of requests, and the master process will restart Hanged worker process.
Each worker process can maintain a persistent connection to MySQL/Memcached/Redis to implement a "connection pool" to avoid repeated connection establishment and is transparent to the program.
When using a database persistent connection, you should Set a fixed number of worker processes and do not use dynamic prefork mode.
The master process uses the epoll model to asynchronously receive and distribute requests, listen to the listening port, and epoll_wait to wait for connections,
and then distribute them to the worker processes in the corresponding pool. The worker process polls to process the connection after accpet request.
If the worker process is not enough, the master process will prefork more processes.
If prefork reaches the pm.max_children upper limit, the worker processes are all busy again.
At this time, the master process The process will suspend the request in the connection queue backlog (the default value is 511).
1 PHP-FPM worker process can only handle 1 request at the same time.
MySQL’s maximum number of connections max_connections is by default 151.
As long as the number of PHP-FPM working processes does not exceed 151, there will be no problem connecting to MySQL.
And under normal circumstances, there is no need to open so many PHP-FPM working processes,
For example, 4 PHP-FPM processes can run up to 4 cores of the CPU,
Then it doesn’t make any sense if you open 40 PHP-FPM processes,
will only take up more memory and cause more CPU context switching will cause worse performance.
In order to reduce the overhead of repeatedly establishing and releasing connections for each request, you can enable persistent connections.
A PHP-FPM process maintains a long connection to MySQL to achieve transparency "Connection pool".
Nginx is separated from PHP-FPM, which is actually very good decoupling. PHP-FPM is specifically responsible for processing PHP requests. One page corresponds to one PHP request.
All requests for static resources in the page are It is processed by Nginx, thus achieving the separation of dynamic and static, and what Nginx is best at is handling high concurrency.
PHP-FPM is a multi-process FastCGI service, similar to Apache’s prefork process model,
For processing only For PHP requests, this model is very efficient and stable.
Unlike Apache (libphp.so), one page has to handle multiple requests, including pictures, style sheets, JS scripts, PHP scripts, etc.
php-fpm has only entered the PHP source code trunk since 5.3, and there was no php-fpm in the previous version.
The spawn-fcgi at that time was a FastCGI process manager that needed to call php-cgi,
In addition, like Apache mod_fcgid and IIS's PHP Manager also need to call the php-cgi process,
But php-fpm does not depend on php-cgi at all, runs completely independently, and does not rely on the php (cli) command line interpreter.
Because php-fpm is a FastCGI service with a built-in php interpreter. It can read the php.ini configuration and php-fpm.conf configuration by itself when starting.
Personally, I think that the number of PHP-FPM working processes should be set to 2 times the CPU The number of cores is enough.
After all, Nginx, MySQL and the system also consume CPU.
It is very unreasonable to set the number of PHP-FPM processes according to the server memory.
Allocate memory to MySQL, Memcached, Redis , Linux disk cache (buffers/cache) services are obviously more suitable.
Excessive PHP-FPM processes will increase the overhead of CPU context switching.
You should try to avoid curl or file_get_contents in PHP code, which may cause Long network I/O time-consuming code.
Pay attention to setting the CURLOPT_CONNECTTIMEOUT_MS timeout to avoid the process being blocked for a long time.
If you want to execute a long time-consuming task asynchronously, you can pclose(popen('/path/ to/task.php &', 'r')); Open a process for processing,
or use the message queue. In short, try to avoid blocking the PHP-FPM worker process.
In php-fpm.conf Set request_slowlog_timeout to 1 second and check the slowlog to see if there is any code that takes more than 1 second.
Optimizing the code can reduce the burden on all PHP-FPM work processes. This is the fundamental way to improve performance.
Operations that allow the CPU to run at full load can be regarded as CPU-intensive operations.
Uploading and downloading are typical I/O-intensive operations, because the time-consuming mainly occurs in network I/O and disk I/O.
Download operations that require PHP authentication can be delegated to Nginx's AIO thread pool:
header("X-Accel-Redirect: $file_path");
As for the upload operation, for example, you can establish a PHP-FPM process pool named upload that listens to the 9001 port.
is specifically responsible for processing the upload operation (distributed through Nginx) to avoid the upload operation from blocking the calculation of the 9000 port. Dense www process pool.
At this time, it doesn’t matter if you open more processes in the upload process pool:
[www]
listen = 127.0.0.1:9000
pm = static
pm.max_children = 4
[upload]
listen = 127.0.0.1:9001
pm = dynamic
pm.max_children = 8
pm.start_servers = 4
pm .min_spare_servers = 4
pm.max_spare_servers = 4
Use the isolation of the pool provided by PHP-FPM to separate computing-intensive and I/O-intensive operations, which can reduce the impact of blocking on the entire PHP application.
Article originally written by open source Chinese blog eechen .
The above introduces the architecture of PHP FastCGI process manager PHP-FPM, including aspects of it. I hope it will be helpful to friends who are interested in PHP tutorials.