Difference between revisions of "Php-fpm"
(→Memcached and PHP Unix Socket configuration for performance) |
|||
Line 1: | Line 1: | ||
<seo title="How to install and configure PHP-FPM on Ubuntu and cPanel" titlemode="append" keywords="PHP-FPM cPanel, How to optimize PHP-FPM, how to enable php-fpm on cpanel" description="How to install and configure PHP-FPM on Ubuntu and CentOS"></seo> | <seo title="How to install and configure PHP-FPM on Ubuntu and cPanel" titlemode="append" keywords="PHP-FPM cPanel, How to optimize PHP-FPM, how to enable php-fpm on cpanel" description="How to install and configure PHP-FPM on Ubuntu and CentOS"></seo> | ||
− | |||
==PHP-FPM Overview== | ==PHP-FPM Overview== |
Revision as of 02:26, 21 February 2018
Contents
PHP-FPM Overview
PHP-FPM (FastCGI Process Manager) is fast. If you have a busy site and want to be able to handle lots of requests then you should at least test out PHP-FPM's performance.
If you plan on using PHP-FPM with PHP 5.5+'s built in opcache, please read the blog post below before you actually do that. Turns out that the opcode cache can be read by any user on the server. This means that if there are say, 10 seperate users, with their own vhosts and directories, and you configure one PHP-FPM pool per user, each user can still see what scripts are cached and their locations. Since they have read access to the cache they could potentially view all this data.
This is obviously a massive security concern, and even if no one exploits this, there is still a chance of scripts being read by the wrong user when generating a page, so websites could possibly be displaying the wrong data / info if there are multiple index.php scripts in the cache.
- Article that explains the issue in detail - https://ikanobori.jp/php55-opcache-shared-hosting.html#
- Official Bug Report - https://bugs.php.net/bug.php?id=69090
I can confirm that this is NOT an issue with FCGI and OPcache, only with PHP-FPM and OPcache
PHP-FPM Configuration Options
PHP-FPM Basic directives
- pm = dynamic: Changes how PHP-FPM wil spin up PHP workers. The default setting uses the other settings to determine how to act. If you want a fixed number of PHP processes running, you can set this to static, if you only want to create new PHP-FPM processes when requested, use "ondemand", personally I like to use "dynamic" and set the lower limit for spare processes to 2 or 3 so that I always have PHP processes up and ready to handle connections.
- pm.max_children = 10: Sets a maximum of 10 PHP-FPM Processes that are allowed to run at the same time. 10 pm.max_children should be a good place to start for most sites. Keep in mind that while this seems low, the average amount of time it takes for a PHP request to complete is somewhere in the 100ms to 200ms range, meaning that if you set this to 1 max children your site could theoretically handle around 5 - 10 requests/s which is a pretty decent amount of traffic if you have that many active connections 24/7.
- pm.start_servers = 4: Sets how many PHP workers are activated when PHP-FPM starts up. Having more start servers for PHP-FPM will help to keep response times low when your site gets a sudden burst of traffic. If you configure PHP-FPM to only have 1 pm.start_servers and all of a sudden 5 people visit your site, your server will need to quickly spawn a few more processes, which can increase website load time slightly. This isn't a huge deal, but if you want to keep response times as low as possible make sure you set the start servers to something like 4 or 5 and make sure you configure the min and max spare servers for PHP-FPM to allow for whatever startserver value you pick.
- pm.min_spare_servers = 4: Sets the minimum number of idle process that PHP-FPM will allow to live. If you start PHP-FPM with 4 processes, and want at least 4 PHP-FPM processes all the time then setting this to 4 is a safe bet, if you want to start with 4 processes, but allow for up to 5 idle processes, set this value to 5.
- pm.max_spare_servers= 6: Sets the maximum number of idle processes PHP-FPM will allow to remain alive. If you want to be aggressive in terms of limiting the amount of RAM and CPU that PHP-FPM can use then you will want to configure pm.max_spare_servers to the same as, or slightly higher than pm.start_servers. You cannot set this value to be lower than the min spare servers, or start servers, otherwise PHP-FPM will not start. I would advise setting this value slightly higher than pm.start_servers
Memcached and PHP Unix Socket configuration for performance
Source: http://arstechnica.com/information-technology/2012/12/web-served-part-3-bolting-on-php-with-php-fpm/
If Memcached is installed, storing PHP session files in RAM can be much more efficient than storing on disk and can also save some IO. To configure this, you should modify the main php.ini file and change session.save_handler to memcached.
php -i | grep php.ini vim /$path/to/php.ini session.save_handler = memcache session.save_path = unix:/tmp/memcached.sock
To change PHP-FPM's listening port to a Unix socket modify the main php-fpm pool's configuration file.
vim /etc/php5/fpm/pool.d/www.conf ##Change## listen = 127.0.0.1:9000 ##To## listen = /var/run/php5-fpm.soc listen.owner = www-data listen.group = www-data
/etc/memcached.conf
# Default connection port is 11211 # -p 11211 # Specify which IP address to listen on. # -l 127.0.0.1 # Listen on a Unix socket -s /tmp/memcached.sock -a 666
If Nginx is in use:
vim /etc/nginx/conf.d/php-sock.conf upstream php5-fpm-sock { server unix:/var/run/php5-fpm.soc; }
http://php.net/manual/en/install.fpm.configuration.php
FPM uses php.ini syntax for its configuration file - php-fpm.conf, and pool configuration files. This means that you need to make sure you update both files if you want to enable a new module, or update settings. If you only update the global php.ini file but do not update php-fpm then you more than likely will not be able to use the module or take advantage of new settings.
How to install Apache 2.4 Event and PHP-FPM on Ubuntu 14.10
Install Packages for Apache 2.4, MySQL, PHP and PHP-FPM
apt-get install apache2 mysql-server php5-mysql php5-fpm php5-gd php5-cli
Use this command to view the loaded modules for [Apache].
apache2ctl -M
Modify PHP-FPM's conf file and make sure its listening on tcp (localhost)
vim /etc/php5/fpm/pool.d/www.conf ;listen = /var/run/php5-fpm.sock listen = 127.0.0.1:9000
Enable proxy_fcgi which also enables proxy. Restart Apache after these are enabled.
a2enmod proxy_fcgi Enabling module proxy. Enabling module proxy_fcgi. service apache2 restart
Now you will want to edit your vhost(s) to pass PHP to FPM. I'm using 000-default since I have no other vhosts on the server, if you already have vhosts then edit them to include the ProxyPassMatch line shown below.
vim /etc/apache2/sites-enabled/000-default.conf ##Add this below CustomLog Line ProxyPassMatch ^/(.*.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/html/$1
You should be able to restart both Apache and php5-fpm and have a working server!
service apache2 restart service php5-fpm restart
To test that apache and php are working correctly, create phpinfo file and load it via browser.
vim /var/www/html/info.php <?php // Show all information, defaults to INFO_ALL phpinfo(); ?>
How to manually install and configure PHP-FPM on cPanel server
Please read this security warning section before you do this on a production server.
Create cpanel rawopts files for Apache and PHP
Create a rawopts file for php, when you run EasyApache these flags will be added when configuring PHP, since PHP-FPM is included in PHP 5.3+ you can enable PHP-FPM rather easily.
vim /var/cpanel/easy/apache/rawopts/all_php5 ##Add these two lines --enable-fastcgi --enable-fpm
Create another rawopts file for apache with a single line.
vim /var/cpanel/easy/apache/rawopts/Apache2_4 ##Add this line --enable-proxy-fcgi=static
Run Easy Apache
Go ahead and run EA now that we have the two rawopts files in place.
/scripts/easyapache
Once EA is done you can run this command to make sure fpm and fastcgi are enabled.
php-config --configure-options
There should now be a php-fpm binary, use which to make sure it's there.
which php-fpm /usr/local/sbin/php-fpm
Create PHP-FPM Configuration Files and Directories
Copy over cPanel's template to /etc/init.d
cp /home/cpeasyapache/src/php-5.5.20/sapi/fpm/init.d.php-fpm.in /etc/init.d/php-fpm chmod a+x /etc/init.d/php-fpm chkconfig php-fpm on
Now we need to edit this file and replace a few sections at the top
vim /etc/init.d/php-fpm ###REPLACE### [email protected]@ [email protected][email protected] [email protected]@/php-fpm [email protected]@/php-fpm.conf [email protected]@/run/php-fpm.pid ###WITH### prefix=/usr/local exec_prefix=${prefix} php_fpm_BIN=${exec_prefix}/sbin/php-fpm php_fpm_CONF=${prefix}/etc/php-fpm.conf php_fpm_PID=/var/run/php-fpm/php-fpm.pid
mkdir /var/run/php-fpm mkdir /usr/local/etc/php-fpm.pool.d
Create global php-fpm.conf
Create the global php-fpm.conf file, I've removed any commented out lines to make the config file easier to look at. This is the global / default configuration for PHP-FPM, we will be adding per user configs in the next step
vim /usr/local/etc/php-fpm.conf ;;;;;;;;;;;;;;;;;; ; Global Options ; ;;;;;;;;;;;;;;;;;; [global] pid = /var/run/php-fpm/php-fpm.pid error_log = /var/log/php-fpm.log process.max = 20 ;;;;;;;;;;;;;;;;;;;; ; Pool Definitions ; ;;;;;;;;;;;;;;;;;;;; [nobody] user = nobody group = nobody listen = 127.0.0.1:9000 pm = ondemand pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3 include=/usr/local/etc/php-fpm.pool.d/*.conf
Create cPanel User php-fpm.conf
This file is an example of how to configure each cPanel user to have their own pool / settings. There are ways to automate all of this, but I am doing this manually so it's easier to understand what is going on. Replace $cpanel_user with the actual cpanel user name.
vim /usr/local/etc/php-fpm.pool.d/$cpanel_user.conf ;;;;;;;;;;;;;;;;;;;; ; Pool Definition ; ;;;;;;;;;;;;;;;;;;;; [$CPANELUSER] user = $CPANELUSER group = $CPANELUSER listen = /var/run/php-fpm/CPANELUSER.sock listen.mode = 0666 pm = ondemand pm.max_children = 10 pm.process_idle_timeout = 10s pm.max_requests = 256
Modify cPanel User vhost to use PHP-FPM
You can either enable all vhosts to use PHP-FPM, or you can just enable certain vhosts to use PHP-FPM, for this example I am just enabling PHP-FPM for a single account.
vim /usr/local/apache/conf/httpd.conf ##Find the vhost that you want to use PHP-FPM with, add this block inside the vhost. <IfModule mod_proxy_fcgi.c> ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/var/run/php-fpm/$cpanel_user.sock|fcgi://localhost/home/$cpanel_user/public_html </IfModule>
Start up PHP-FPM, then restart apache
service php-fpm start service httpd restart
How to Enable PHP-FPM Access Logging
By default, the access log for PHP-FPM is not enabled. The error log is enabled and located at /var/log/php-fpm.log so if you do enable the access log I suggest setting a location that is in /var/log to make it easier to view both files.
These instructions assume that you are using a cPanel server and have used the cphstack script to get PHP-FPM installed and running. If you are not using cPanel then you should be able to modify the pool conf file located under /usr/local/etc/php-fpm.pool.d/
vim /opt/xstack/cphstack/php-fpm.pool.d/$domain1.com.conf
About half way down the file you should see a few lines that are commented out. You need to remove the ";" before the two lines below. You can name the access.log whatever you want, in my case I named it php-fpm.access.log. You can also modify the default PHP-FPM log formatting to include some useful metrics like process size in MB and the response time per request.
access.log = /var/log/php-fpm.access.log access.format ="%t "%{megabytes}M MB %{seconds}d seconds" \"%m %f\" %s"
Note that I added "MB" and "seconds" to the format line so that you can tell what the values are later on when you look at the logs. If you don't label the columns then you would just see a "5" instead of "5 MB", or "0.100" instead of "0.100 seconds"
Save the configuration file, then restart PHP-FPM
service php-fpm restart
At this point you should be able to tail the access log and load a page and see new logs come in.
tail -f /var/log/php-fpm.access.log
Below is an example of what the PHP-FPM access log looks like once you've enabled and customized the output.
17/Mar/2015:13:10:37 -0400 5 MB 0.164 seconds "GET /home/$user/public_html/wiki//index.php" 200 17/Mar/2015:13:10:37 -0400 3 MB 0.033 seconds "GET /home/$user/public_html/wiki//load.php" 200
To view the peak memory amount that was allocated during a request you can add %M to the access log
; %M: peak of memory allocated by PHP ; it can accept the following format: ; - %{bytes}M (default) ; - %{kilobytes}M ; - %{kilo}M ; - %{megabytes}M ; - %{mega}M
To view per request response times for PHP-FPM you can add %d, by default it will output response times in seconds, so 0.100 is 1/10 of a second or 100 milliseconds.
; %d: time taken to serve the request ; it can accept the following format: ; - %{seconds}d (default) ; - %{miliseconds}d ; - %{mili}d ; - %{microseconds}d ; - %{micro}d