14

I have done some investigations and I have found this to calculate and adjust pm.max_children value

https://myshell.co.uk/blog/2012/07/adjusting-child-processes-for-php-fpm-nginx/

but for example :

  • I have 8Gb on my server
  • I'm hosting 30 websites
  • php-fpm average process size around 40mb
  • php-fpm max process size around 80mb
  • I want to allocate 5Gb max of my memory to php-fpm processes

If I apply this :

pm.max_children = Total RAM dedicated to the web server / Max child process size

So in my case :

pm.max_children = 5120 / 80 = 64

But If I add pm.max_children = 64 on each php-fpm website conf files, this means every website can use 64 children process X size of 1 process (ex 40mb) = 2560Mb

And If we imagine, at the same time, all the 30 website have reach the pm.max_children value, we will have : 2560Mb (max per website) x 30 websites = 76 800 Mb

Am I correct?

Si yes, this means when many websites are hosted on the same server, we have to divide the result of the calcul pm.max_children = 5120 / 80 = 64 by the number of websites hosted (here 30).

So 64 / 30 = 2,1 and pm.max_children = 2 per website

Is it correct or not?

Thanks

TooNetCreation
  • 153
  • 1
  • 2
  • 8
  • nobody has infos about that? – TooNetCreation Nov 11 '18 at 13:12
  • Only if you are using different FPM pool for every website a value of 2 does this. The common approach (because of sharing resources) is to have one FPM pool. Than you can limit it to the higher value if you watch for RAM as a capacity limit. Actually you should have enough CPU to handle 64 concurrent processes as well. – Jens Bradler Nov 12 '18 at 04:30
  • hello, thank you for your feedback. for the moment I have 1 pool for all 30 websites. the server has 4 vCPU and 8 Gb of RAM. I don't know if it would be better to have one FPM pool per website or 1 pool for all websites? for maintenance reasons, 1 pool for every website could be interesting. but for performances reasons I don't know. what's your opinion? – TooNetCreation Nov 12 '18 at 08:46
  • hello, do you have any advice on how to use php-fpm pools? would it be better to have 1 pool for many websites or 1 pool for every website? thanks – TooNetCreation Nov 13 '18 at 09:58

2 Answers2

12

Your calculation is correct from what I gather.

Having many webs on the same server works only as long as not all webs use all available resources at the same time. This is what people usually call overprovisioning.

However, I suggest not to simply calculate pm.max_children around the available RAM, but around how many workers are actually necessary for the webs to function properly. Start with something lower and monitor the the php-fpm.log. If the max_children setting is reached, you will find it in the log and you can increase it.

Also, make sure that the PHP workers only live as long as necessary. For example, the following configuration will let a pool use up to 32 PHP workers if there is a burst of requests, but each worker will exit after 3 seconds of inactivity and free valuable RAM:

pm = ondemand
pm.max_children = 32
pm.process_idle_timeout = 3s

Use the ondemand process manager if you are low on RAM. It is a bit slower than the dynamic pm, but doesn't waste RAM for inactive websites.

If you want to control the total number of PHP processes, there is a setting called process.max in php-fpm.conf. I have never used it, but it seems to me you could use it to ensure that there are never more than a certain number of workers, regardless of how the pools are configured.

By the way, it is a very good idea to use separate pools for separate webs belonging to separate users. That way you won't have any problems with user permissions or with data cached from other webs.

Oliver
  • 5,883
  • 23
  • 32
  • Thank you for you feedback. I have for the moment 8 GB of RAM...maybe too short ? yes **on demand** could be much **slower** than **dynamic**, but much more secure indeed. – TooNetCreation Nov 13 '18 at 20:05
  • 2
    I think you should just try it and see how it performs. Compare `ondemand` and `dynamic`, don't forget that you can also mix them (e.g. `dynamic` for the busier webs, `ondemand` for less important ones). – Oliver Nov 14 '18 at 07:17
  • ok. I see. About config, I can keep the main config file here **/etc/php/7.2/fpm/php-fpm.conf** where I set up **pm = ....** with **pm.max_children = ....** etc... and I can have 1 pool for every website here **/etc/php/7.2/fpm/pool.d/** where I set up for each website a conf file containing **user = ...** + **group = ...** + **listen =...** + **listen.owner = ...** + **listen.group = ...** . Am I correct? – TooNetCreation Nov 14 '18 at 08:04
  • No idea if it works that way. Usually `pm` settings are per-pool. Check out the default config files and work from there rather than trying to do something else. – Oliver Nov 14 '18 at 09:44
  • I have seen that **PM** settings are available in this file **/etc/php/7.2/fpm/php-fpm.conf** but can also be added in this file **/etc/php/7.2/fpm/pool.d/example.conf** if we use 1 pool per website. but in my case, 1 pool per website will contain only settings for user and group. the **PM** settings will be global, that's why I want to manage it in this file **/etc/php/7.2/fpm/php-fpm.conf** . also **pm.max_children** can be used globally instead of in each pool file no? – TooNetCreation Nov 14 '18 at 10:17
  • I have done some tests and **pm.max_children** directive cannot be added into this file **/etc/php/7.2/fpm/php-fpm.conf**. Have to be added on **/etc/php/7.2/fpm/pool.d/www.conf** or on dedicated file like **/etc/php/7.2/fpm/pool.d/example.conf**. what I don't undertand is : how to declare **pm.max_children = 50 ** for all the websites hosted but having separate pools for separate webs to define user and groups permissions? – TooNetCreation Nov 14 '18 at 12:53
  • As I said, the `pm` settings are per-pool. But there is a `process.max` setting that allows to globally limit the number of PHP workers. – Oliver Nov 14 '18 at 13:05
  • Ok I see. So if this is mandatory to allow **pm.max_children** per pool with my server settings described in my first post, what is the best way to calculate a balanced **pm.max_children** for all websites? – TooNetCreation Nov 14 '18 at 13:21
  • do you have an idea following my last comment? – TooNetCreation Nov 15 '18 at 11:19
  • No, I won't try to calculate your `pm.max_children` for you and I guess nobody else will. I don't know anything about how your websites are used or about the nature of your PHP code. I can only repeat what I wrote in my answer: Start with some value which you think is high enough and monitor the log. Use `ondemand` to make sure you don't waste memory. If you want to ensure you don't have too many PHP workers running, set `process.max` to something like 64. – Oliver Nov 15 '18 at 14:01
  • Yes I was not asking to calculate **pm.max_children** for me. my question was just to get your opinion about calculation process and If there is any possibility to define a **pm.max_children** value for ALL websites, instead of define it website per website ? – TooNetCreation Nov 15 '18 at 18:06
2

I can only give you an advise based on our experiences.

We have only one PHP-FPM pool running to share resources (CPU and RAM).

Multiple pools allow different user accounts (e.g. www-data1, www-data2 ...) and may help to restrict access. Additionally you can assign different values for CPU and RAM consumption if required.

However following example uses only one pool:

; www.conf
;
; set pool management to have a fixed number of php workers
pm = static
; number of php processes (6 processes per CPU core)
pm.max_children = 48

I recommend using static pool management. This means there are always a fixed number of PHP workers.

; www.conf
;
; redirect worker stdout and stderr into main error log
catch_workers_output = yes

This might be helpful if your application runs into errors.

; php-fpm.conf
;
emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 10s

This is some basic life monitoring of your running PHP workers.

Do not forget to restart your PHP-FPM service after these changes.

Jens Bradler
  • 6,133
  • 2
  • 16
  • 13
  • many thanks for all these details. Ok so this means I can keep the main config file here **/etc/php/7.2/fpm/php-fpm.conf** where I set up **pm = ....** with **pm.max_children = ....** etc... and I can have 1 pool for every website here **/etc/php/7.2/fpm/pool.d/** where I set up for each website a conf file containing **user = ...** + **group = ...** + **listen =...** + **listen.owner = ...** + **listen.group = ...** . Am I correct? – TooNetCreation Nov 13 '18 at 19:59