PHP-FPM

PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation, which allows to run PHP as a separate process and has some additional useful features:

  • Adaptive process spawning
  • Basic statistics
  • Advanced process management with graceful stop/start
  • Ability to start workers with different uid/gid/chroot/environment and different php.ini
  • Stdout & stderr logging
  • Emergency restart in case of accidental opcode cache destruction
  • Accelerated upload support
  • Support for a "slowlog"
  • Enhancements to FastCGI, such as `fastcgi_finish_request()`` - a special function to finish request & flush all data while continuing to do something time-consuming (video converting, stats processing, etc.)

FastCGI is a binary protocol for interfacing interactive programs with a web server. FastCGI is a variation on the earlier Common Gateway Interface (CGI); FastCGI's main aim is to reduce the overhead associated with interfacing the web server and CGI programs, allowing a server to handle more web page requests at once.

CGI is an interface which tells the webserver how to pass data back and forth to and from an application. More specifically, it describes how request information is passed in environment variables (such as request type, remote IP address), how the reqeust body is passed in via standard input, and how the response is passed out via standard output.

PHP-FPM uses “persistent processes”. Rather than killing and re-creating a process on each request, FPM will re-use processes.

Install PHP-FPM

sudo apt-get install -y php5-fpm
sudo service php5-fpm start

Configure PHP-FPM

FPM configuration includes php.ini file, conf.d directory, php-fpm.conf global configuration and pool.d directory with FPM’s resource pools configuration (default www.conf).

drwxr-xr-x 4 root root 4.0K May 31 00:26 .
drwxr-xr-x 4 root root 4.0K May 31 00:26 ..
drwxr-xr-x 2 root root 4.0K May 31 00:26 conf.d
-rw-r--r-- 1 root root 4.5K Apr 17 11:57 php-fpm.conf
-rw-r--r-- 1 root root  69K May 31 00:26 php.ini
drwxr-xr-x 2 root root 4.0K May 31 00:26 pool.d

Global Configuration

Global configuration is /etc/php5/php-fpm.conf

  • error_log = /var/log/php5-fpm.log error log
  • log_level = notice the log level of reporting to the error log
  • emergency_restart_threshold = 0 number of child processes to exit with errors hat will trigger a graceful restart of FPM.
  • emergency_restart_interval=0 interval of time used to determine when a graceful restart will be initiated
  • daemonize = yes run PHP-FPM as a daemon, in the background.
  • include=/etc/php5/fpm/pool.d/*.conf include all confguration files

Resource Pools

PHP-FPM can have separate resource “pools”. Each pool represents an “instance” of PHP-FPM, which can be used to send PHP requests.

Separate resource pool configurration has some advantages:

  • Each resource pool listens on its own socket. They do not share memory space, a boon for security.
  • Each resource pool can run as a different user and group. This allows for security between files associated with each resource pool.
  • Each resource pool can have different styles of process management, allowing to give more or less power to each pool.

listen = /var/run/php5-fpm.sock by default, PHP-FPM listens on a Unix socket. A “socket” is merely a means of communication. Unix sockets are faux-files which work to pass data back and forth. A TCP socket is the combination of an IP address and a port, used for the same purpose. A Unix socket is a little faster than a TCP socket, but it is limited in use to the local file system.

If PHP-FPM process will always live on the same server as web server, then it can have default Unix socket, but if PHP-FPM is communicating to a remote server, then it needs to use a TCP socket.

Change socket to a TCP listen = 127.0.0.1:9000

This listens on the loopback network interface (localhost) on port 9000. If PHP-FPM needto listen for remote connections it needs to be binded to the other network interfaces:

# Binding to network 192.168.12.*
listen = 192.168.12.12:9000

The three most important settings as far as performance goes are:

pm setting determines how the process manager will control the number of child processes. You can choose static, ondemand, or dynamic.

  • ondemand is used for lower traffic websites.Processes do not sit there doing nothing if they're not going to be used, so they can only be spawned when they are requested.
  • If a webserver consistently has traffic, it's better to switch to dynamic. Dynamic settings will ensure PHP-FPM have x number of processes ready to work. pm.start_servers = 5 is set to 10% or so of your max_children.

pm.min_spare_servers = 3 This ensures PHP-FPM always has 3 spare processes. So if it has 35 busy processes, it'll have 38 PHP-FPM processes, with 3 ready to handle incoming requests.

pm.max_spare_servers = 6 If a webserver has a spike in traffic that requires spawning more than 6 processes, this number will get rid of those processes to get back to 6 once they're not needed anymore.

Keep in mind pm.start_servers, pm.min_spare_servers and pm.max_spare_servers are only used for dynamic.

pm.max_children option is mandatory no matter what pm mode is choosen. It is very important, because it controls the maximum number of FPM processes that the system can run at the same time.

It's required to pick a reasonable number depending on how much memory is on the server.

A good way of figuring out this number is to think in terms of available memory. If you have 2GB: you assume Nginx + other processes will use at most 300MB, and you assume 20MB/process, you could do ( 2000MB - 300MB ) / 20 MB = roughly 90. ( MAX_MEMORY - 300MB ) / 20 MB.

pm.max_children = 90

pm.max_requests setting determines how many requests each child process should handle before respawning. Useful setting to avoid memory runoff from 3rd party libraries and such.

Sources: