Apache and lighttpd replaced by nginx for PHP application
A while back I wrote an article Switching from Apache HTTP Server to Lighttpd - Installing Lighttpd. Back then I migrated static stuff to lighttpd but left the dynamic stuff (PHP) with Apache.
I was never really satisfied with the speed of our system under load. I tried and tried. I optimized a lot of stuff in the backend and with the database. Most of the time I found a switch to make the system just a bit faster. Read Retrospective on three years of Seagull development if you are interested in the whole story.
In the last couple of weeks I ran out of ideas on where to improve next (without the need of rewriting too much code). I remembered using Squid years ago. I had a look at the newest version (3.0) and my interest in Squid stopped pretty soon after reading through the documentation. It was just not the software I needed.
I dived into spreading the load to multiple backends using HAproxy which by the way has a super active community. Check the mailinglist. The maintainer Willy is doing a great job. Learning about HAproxy I stumbled across the webserver nginx (pronounced engine x) numerous times. Learning about nginx I stumbled across the reverse proxy Varnish which is the proxy solution I hoped Squid would be. Furtherdown the line I ran into PHP-FPM - the PHP FastCGI Process Manager - which should not stay unmentioned.
So I read lots of blog posts, mails from mailinglists, documentation, articles, visited several forums and also learned many new things in a few wikis. So after getting the idea I had my stack together: Varnish -> HAproxy -> nginx -> PHP -> MySQL
Time to test it out! Varnish comes in a relatively uptodate package for my favorite distribution OpenSuSE (currently running 10.3 on 6 systems). HAproxy is available in a fresh version. nginx is theoretically available. It cannot install it though because of a package management conflict. So I downloaded the source for the newest stable version (0.6.3 as time of writing) and compiled it.
# wget http://sysoev.ru/nginx/nginx-0.6.32.tar.gz
# ./configure –prefix=/opt/software/nginx-0.6.32 –user=nginx –group=nginx –without-mail_pop3_module –without-mail_imap_module –without-mail_smtp_module
# make && make install
I did not need to install any extra packages. Frankly spoken I do have all the packages for compilation of C/C++ installed.
# cd /opt/software
# ln -s /opt/software/nginx-0.6.32 nginx
I always set a symlink to the currently used package. That way it is easy to replace the package when new versions come out. I can compile and install the new version and just switch the symlink.
Next thing I had to compile was a patched PHP version. So download the sources at php.net and the patches at the PHP-FPM site.
Unpack the PHP source:
# tar xjvf php-5.2.6.tar.bz2
Patch the source:
# gzip -cd php-5.2.6-fpm-0.5.8.diff.gz | patch -d php-5.2.6 -p1
Configure PHP (adjust your settings accordingly):
LDFLAGS=”-L/usr/lib64″ ./configure –with-curl –disable-debug –enable-libxml –enable-session –with-pcre-regex –enable-xml –with-bz2 –with-zlib –enable-exif –enable-inline-optimization –enable-soap –enable-sockets –with-xmlrpc –without-pear –with-libdir=lib64 –with-mysql –with-mysqli –enable-mbstring –with-mcrypt –with-mhash –with-mime-magic –with-jpeg-dir=/usr/lib64 –with-png-dir=/usr/lib64 –with-gd –enable-gd-native-ttf –with-ttf –with-freetype-dir –enable-ftp –enable-zend-multibyte –with-openssl –enable-force-cgi-redirect –with-pcre-regex –without-sqlite –without-mm –enable-fastcgi –enable-bcmath –enable-fpm –quiet –prefix=/opt/software/php5.2.6-fpm
Compile and install:
# make & make install
Adjust the PHP-FPM settings to fit your needs. You can find more info on this and related subjects in the PHP-FPM documentation.
# vim /opt/software/php/etc/php-fpm.conf
Start PHP-FPM:
# /opt/software/php/bin/php-cgi –fpm
Have a look in the log files:
# /opt/software/php/logs/php-fpm.log
Now you can connect through your webserver to fast-cgi processes. I use nginx as webserver (see above). Advantages and disadvantes of fast-cgi vs. mod-based approaches et al have been covered elsewhere. For me this makes perfectly sense and works extremly well.
After playing around with Varnish for a while I decided I do not need HAProxy ATM. Varnish can do all the decisions I need to make based on HTTP headers. I configured Varnish’s config file (here: vcl.conf) by reading lots of examples on the net and trial and error.
If I find more time and anyone is interested I post more details on the configuration of nginx and Varnish. But for now I want to publish this post as it has been sitting here for a while already.
PS: If people say content is king they are absolutely right. But never forget in the internet speed is Kaiser!