We set up the blog, did the first round of optimization and secured it last time. Today we optimize how Apache and PHP run.

Let’s start with PHP.

PHP

PHP, as configured out of the box, runs inside the same process as Apache. This isn’t optimal because it can take up a bunch of memory in all of the web server processes. Not only that but the cache of PHP’s code doesn’t seem to be as shared as it could be.

An analogy is thinking of Apache as a small sports car. PHP requires some other stuff to be bolted onto that car. When you’re done the original sports car is like an SUV. PHP-FPM is a way of running the PHP code in another process. Apache stays mean and lean and PHP does only what it needs to. Both scale well. Not only that but we can configure Apache to run multi-threaded and quicker and even lower memory! But that’s the second part of this post.

Let’s start!

First off, let’s configure PHP-FPM.

$ sudo nano /etc/php-fpm.d/www.conf

What you want to do is set things up like this:


listen = /var/run/php-fpm/php-fpm.sock

listen.owner = apache
listen.group = apache
listen.mode = 0664

user = apache
group = apache

pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10

(I’m leaving out the comments that start with “;” in this case)

What this sets up is a process that’s listening to a UNIX socket on /var/run/php-fpm/php-fpm.sock. This is like listening to an internet socket but a bit quicker.

We’re also setting this to run as the same user as Apache.

Last we’re making this max out at 20 PHP processors. If we’re running this on a bigger machine, you can scale this up.

Next, let’s start this up!


$ sudo chkconfig php-fpm on
$ sudo service php-fpm start
Starting php-fpm:                     [  OK  ]

Now we have to get Apache to use this instead of the default way of running PHP.

$ sudo yum install httpd-devel apr-devel apr
$ cd /tmp
$ wget http://www.fastcgi.com/dist/mod_fastcgi-current.tar.gz
$ tar xfvz mod_fastcgi-current.tar.gz 
$ cd mod_fastcgi-2.4.6/
$ cp Makefile.AP2 Makefile
$ make top_dir=/usr/lib/httpd/
$ sudo make install top_dir=/usr/lib/httpd

I’ll walk through what’s going on here.

  • sudo yum … – Gets a few more packages
  • cd – Change Directory
  • wget – Download the latest fast CGI module
  • tar – Extract the source code
  • cd – Change directory into what just got extracted (you might need to change the version number depending on what’s latest at the time)
  • cp – Copy the makefile so we’re using the right one
  • make – Compile the module
  • sudo make install – Install the module into Apache!

Next, we have to set up a directory for Apache to use.

$ sudo mkdir /var/www/fcgi-bin
$ sudo cp $(which php-cgi) /var/www/fcgi-bin/
$ sudo chown -R apache: /var/www/fcgi-bin
$ sudo chmod -R 755 /var/www/fcgi-bin
  • mkdir – Makdirectory
  • cp – Copy
  • chown – Change ownership to Apache
  • chmod – Change mode so only Apache can write to it.

Apache

Finally, we need to add an Apache config:

$ sudo nano /etc/httpd/conf.d/php-fpm.conf

Since this is a new file, just paste this in:

LoadModule fastcgi_module modules/mod_fastcgi.so

<IfModule mod_fastcgi.c>
    ScriptAlias /fcgi-bin/ "/var/www/fcgi-bin/"
    FastCGIExternalServer /var/www/fcgi-bin/php-cgi -socket /var/run/php-fpm/php-fpm.sock -pass-header Authorization
    AddHandler php-fastcgi .php
    Action php-fastcgi /fcgi-bin/php-cgi
    DirectoryIndex index.php
</IfModule>

This will load the module we just installed and point it at the socket that the fpm module is listening on.

Lastly, we need to unconfigure the old way of running PHP and restart Apache.

$ sudo mv /etc/httpd/conf.d/php.conf  /etc/httpd/conf.d/php.conf-old
$ sudo service httpd restart

At this point you should go back to your browser and make sure things work. Things should. :-)

At this point we just need to configure Apache to use the multi-threaded way of running things.

$ sudo nano /etc/sysconfig/httpd

Just find the line that looks like

#HTTPD=/usr/sbin/httpd.worker

…and remove the “#” that comments it out.

Restart the service one last time and you should be good to go!

$ sudo service httpd restart

Next time, we’ll run some benchmarks against this! (I’ll also go into some of the details about what we just did with before and after benchmarks)

(Updated 2014-03-30 – Some of the configs for the PHP-FPM were jibbered)