PHP-FPM creating too many proccesses & eating all the CPU

This is an urgent question. My AWS instance with 4GB RAM and 2vCPU is getting exhausted by too many php-fpm processes.

PHP-FPM starts creating too many processes which it didn't do earlier. This results in slow loading of the site. I'm not able to figure out why this is happening.

My php.ini config:

html errors = off
precision = 14
output_buffering = 4096
serialize_precision = 17
max_execution_time = 300
max_input_time = 60
max_input_vars = 5000
log_errors_max_len = 1024
post_max_size = 27M 
upload_max_filesize = 27M 
max_file_uploads = 20
default_socket_timeout = 60
pdo_mysql.cache_size = 2000
memory_limit = 256M

www.conf:

pm = dynamic
pm.max_children = 35
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 20
pm.max_requests = 1000

screenshot of top command: top command output


Solution 1:

Answering your question

In www.conf change this (35 processes)

pm.max_children = 35
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 20
pm.max_requests = 1000

to this (8 processes) - or whatever number you like

pm.max_children = 8
pm.start_servers = 4
pm.min_spare_servers = 1
pm.max_spare_servers = 2
pm.max_requests = 1000

You may also like to correct this typo

max_file_uploads = 20 = 20

Answering the question in the comments

As background, pm.max_children is how many PHP threads are available to service requests. If not thread is available a request will queue, up to the web server timeout, until a work is available.

PHP is very memory intensive, and quite CPU intensive. If you have enough RAM (say) 10 PHP threads, but allocate 30, your server will swap and performance will be terrible. If you over-allocated CPU it will go slower, but it won't be as bad as insufficient RAM.

In general, you should work how how many PHP workers can run without exhausting your servers RAM. Let's say your server is using 2GB RAM with PHP turned off, and each thread uses 100MB of RAM, you can have about 20 PHP workers. You should try to avoid saturating RAM, as it's used as a disk cache, so leave some RAM free.

You need to find a balance between slow PHP threads and queuing. No-one can do that for you, it will be experimentation until your server is fully utilized but not struggling. But, to start, let's say a maximum of 10 threads and go from there. Use "top" to monitor free memory, but for memory you may need to use the "res" (resident in memory, I assume) column rather than "virt" to estimate PHP RAM use.

Opcache

I suspect (but don't know for sure) that advice to enable the opcache is outdated, as PHP7 is fairly well optimised and likely enabled by default.

Caching

The key to good performance with PHP is caching. Anonymous users hitting a page that isn't customised can often be cached, even if it's only for 1 / 5 / 60 seconds it can be a big help on a highly loaded server. Make sure your caching headers properly describe the page expiry, then configure Nginx / Apache to cache appropriately - if you're using a web server.

You can also cache static resources on a CDN, such as CloudFront / CloudFlare (note that CloudFlare has a free tier and works well with AWS). It won't say much CPU or RAM, but it will save bandwidth. Every bit helps on a loaded server.