Tag Archives: php-fpm

PHP-FPM pool sizes explanation

If you see these settings in a PHP-FPM config. file (real life example):

pm.max_children = 100
pm.start_servers = 30
pm.min_spare_servers = 30
pm.max_spare_servers = 100

What does it actually mean?

1) There will never be less than 30 processes (because it starts with 30, and minimum spare is 30)

2) There will always be at least 30 idle processes, except when more than 70 are in use.

3) Idle processes will never be killed off, unless they hit pm.max_requests (because the number of processes cannot possibly exceed the maximum spare)

Too many idle processes is bad, because they use up virtual memory. It is especially bad on a server with no swap, because then they can’t be shunted out of RAM to make room for active processes.
Also, remember that the settings are per-pool. On this particular server, there were three pools with identical settings. The result was that there were never less than 90 PHP processes, even if all were idle.

So please be mindful of the law of unintended consequences, especially when creating additional PHP FPM pools.

 

Credits to my ex colleague Danny 🙂

Apache 2.2 + PHP-FPM on Centos

WITHOUT disabling MOD_PHP in Apache

>> Compile module:
yum -y install httpd-devel gcc
mkdir /tmp/fastcgi
cd /tmp/fastcgi
wget https://github.com/whyneus/magneto-ponies/raw/master/mod_fastcgi-SNAP-0910052141.tar.gz
tar -zxf mod_fastcgi*
cd mod_fastcgi-*
make -f Makefile.AP2 top_dir=/usr/lib64/httpd
cp .libs/mod_fastcgi.so /usr/lib64/httpd/modules/

>> Enable the module:
echo "LoadModule fastcgi_module /usr/lib64/httpd/modules/mod_fastcgi.so" > /etc/httpd/conf.d/fastcgi.conf


>> Install php-fpm and create pools like this:
[$USER]
listen = /dev/shm/$USER-php5-fpm.sock
user = $USER
group = $USER
listen.owner = $USER
listen.group = apache
listen.mode = 0666
pm = dynamic
pm.max_children = 35
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 25
slowlog = /var/log/php-fpm/$USER-slow.log
php_admin_value[error_log] = /var/log/php-fpm/$USER-error.log
php_admin_flag[log_errors] = on


>> Add this in the VHOST configuration (before the end of </VirtualHost>)
FastCGIExternalServer /dev/shm/$USER-php.fcgi -socket /dev/shm/$USER-php5-fpm.sock -flush -idle-timeout 1800
AddHandler php-fpm .php
Action php-fpm /php.fcgi
Alias /php.fcgi /dev/shm/$USER-php.fcgi
DirectoryIndex index.php
<FilesMatch "\.php$">
    SetHandler php-fpm
</FilesMatch>


>> Double check php.ini for 'session.save_path'. 
session.save_path = "/tmp"
;session.save_path = "/var/lib/php/session"

 

One liners alternative for apachebuddy


average apache process mem usage

ps -H h -ylC httpd | perl -lane '$s+=$F[7];$i++;END{printf"Avg=%.1fMB\n",$s/$i/1024}' 
ps -H h -ylC apache2 | perl -lane '$s+=$F[7];$i++;END{printf"Avg=%.1fMB\n",$s/$i/1024}' 

highest process mem usage cd

ps -H h -ylC httpd | awk 'function max(x){i=0;for(val in x){if(i<=x[val]){i=x[val];}}return i;}function min(x){i=max(x);for(val in x){if(i>x[val]){i=x[val];}}return i;}/^#/{next}{a[$8]=$8;next}END{minimum=min(a);maximum=max(a);print "Max = "maximum / 1024 "MB";print "Min = "minimum / 1024"MB"}' 
ps -H h -ylC apache2 | awk 'function max(x){i=0;for(val in x){if(i<=x[val]){i=x[val];}}return i;}function min(x){i=max(x);for(val in x){if(i>x[val]){i=x[val];}}return i;}/^#/{next}{a[$8]=$8;next}END{minimum=min(a);maximum=max(a);print "Max = "maximum / 1024 "MB";print "Min = "minimum / 1024"MB"}'

php-fpm – www pool average

for pid in $(ps aux | grep fpm | grep "pool www" | awk '{print $2}'); do pmap -d $pid | tail -1 ; done | sed 's/K//' | awk '{sum+=$4} END {print sum/NR/1024}'

php-fpm – ALL active pools average memory

Ubuntu: cd /etc/php5/fpm/pool.d
Centos: cd /etc/php-fpm.d/
for pool in `ls *.conf` ; do POOL="`echo $pool | sed 's/\.conf//'`" ; echo -e "\n$POOL" ; for pid in $(ps aux | grep fpm | grep "pool $POOL" | awk '{print $2}'); do pmap -d $pid | tail -1 ; done | sed 's/K//' | awk '{sum+=$4} END {print sum/NR/1024}' ;  done

MANUAL CHECKS (understanding)

# ps aux | grep apache2 (or httpd)

USER       PID %CPU PerformanceOptimized %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

-> RSS is the real memory value
-> VSZ is the one that it might reach (important mostly for MySQL)

# Quicker way is to do top and than press ‘>’

WordPress PHP-FPM and Apache (with variables)

Sample setup for Apache virtual host and PHP-FPM pool with variables instead hard coded user details.
This could be handy if your are scripting your deploy (e.g. with Ansible).

In our example we are using the following:

Domain: example.com
SFTP user: example.com
Document root: /var/www/vhosts/example.com/httpdocs/

<VirtualHost *:80>
        ServerName example.com
        ServerAlias www.example.com

        DocumentRoot /var/www/vhosts/example.com/httpdocs
        <Directory /var/www/vhosts/example.com/httpdocs>
                require all granted
                Options Indexes
                AllowOverride All
        </Directory>

        ErrorLog "logs/example.com-error_log"
        CustomLog "logs/example.com-access_log" combined env=!forwarded
        CustomLog "logs/example.com-access_log" proxy env=forwarded

	# Configure proxy connector
	<Proxy "unix:/dev/shm/example.com-php5-fpm.sock|fcgi://php-fpm">
    		# we must declare a parameter in here (doesn't matter which) or it'll not register the proxy ahead of time
	    	ProxySet disablereuse=off
	</Proxy>
	#
	# Redirect to the proxy connector
	<FilesMatch \.php$>
    		SetHandler proxy:fcgi://php-fpm
	</FilesMatch>


        <Directory /var/www/vhosts/example.com/httpdocs/wp-content/uploads>
            # Important for security, prevents someone from
            # uploading a malicious .htaccess
            AllowOverride None

            SetHandler none
            SetHandler default-handler

            Options -ExecCGI
            php_flag engine off
            RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo
            <Files *>
                    AllowOverride None

                    SetHandler none
                    SetHandler default-handler

                    Options -ExecCGI
                    php_flag engine off
                    RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo
            </Files>
        </Directory>
</VirtualHost>

Create a file called example.com.conf in /etc/php-fpm/pool/

[example.com]

listen = /dev/shm/$pool-php5-fpm.sock
user = $pool
group = $pool
listen.owner = $pool
listen.group = apache
listen.mode = 0666

pm = dynamic
pm.max_children = 35
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 25
slowlog = /var/log/php-fpm/$pool-slow.log
php_admin_value[error_log] = /var/log/php-fpm/$pool-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session/$pool

Apache 2.4 + PHP-FPM Ubuntu 14.04

apt-get install php5-mysql php5-fpm php5-gd php5-cli apache2-mpm-worker libapache2-mod-fastcgi

Create a php-fpm pool /etc/php5/fpm/pool.d/$USER.cnf

[$USER]
user = $USER
group = www-data
listen = 127.0.0.1:9000
listen.owner = www-data
listen.group = www-data

pm = dynamic
pm.max_children = 100
pm.start_servers = 35
pm.min_spare_servers = 15
pm.max_spare_servers = 35
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session/$USER
chdir = /

In Vhost:

ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/vhosts/MYDOMAIN.COM/public_html/$1

Enable/disable modules and restart services

a2dismod mpm_prefork php5 && a2enmod actions fastcgi alias mpm_event proxy_fcgi proxy

service php5-fpm restart
service apache2 restart

Don’t forget to enable “index.php” in your DirectoryIndex directive, if using PHP-FPM! Also, remove any PHP directives from Apache, and configure in PHP-FPM instead.

Apache 2.2 + PHP-FPM (Centos 6)

WITHOUT disabling MOD_PHP in Apache

Compile module:

yum -y install httpd-devel gcc
mkdir /home/rack/fastcgi
cd /home/rack/fastcgi
wget https://github.com/whyneus/magneto-ponies/raw/master/mod_fastcgi-SNAP-0910052141.tar.gz
tar -zxf mod_fastcgi*
cd mod_fastcgi-*
make -f Makefile.AP2 top_dir=/usr/lib64/httpd
cp .libs/mod_fastcgi.so /usr/lib64/httpd/modules/

Enable the module:

echo "LoadModule fastcgi_module /usr/lib64/httpd/modules/mod_fastcgi.so" >> /etc/httpd/conf.d/fastcgi.conf

Install php-fpm and create pools like this:

[$USER]
listen = /dev/shm/$USER-php5-fpm.sock
user = $USER
group = $USER
listen.owner = $USER
listen.group = apache
listen.mode = 0666
pm = dynamic
pm.max_children = 35
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 25
slowlog = /var/log/php-fpm/$USER-slow.log
php_admin_value[error_log] = /var/log/php-fpm/$USER-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session/$USER/

NOTE: Make sure the path /var/lib/php/session/$USER/ exists and its owned by $USER!

Add this in the VHOST configuration (before the end of </VirtualHost>) )

FastCGIExternalServer /dev/shm/$USER-php.fcgi -socket /dev/shm/$USER-php5-fpm.sock -flush -idle-timeout 1800
AddHandler php-fpm .php
Action php-fpm /php.fcgi
Alias /php.fcgi /dev/shm/$USER-php.fcgi
DirectoryIndex index.php
<FilesMatch "\.php$">
    SetHandler php-fpm
</FilesMatch>