Always Get Better

Setting up WordPress with nginx and FastCGI

All web site owners should feel a burning need to speed. Studies have shown that viewers waiting more than 2 or 3 seconds for content to load online are likely to leave without allowing the page to fully load. This is particularly bad if you’re trying to run a web site that relies on visitors to generate some kind of income – content is king but speed keeps the king’s coffers flowing.

If your website isn’t the fastest it can be, you can take some comfort in the fact that the majority of the “top” web sites also suffer from page load times pushing up into the 10 second range (have you BEEN to Amazon lately?). But do take the time to download YSlow today and use its suggestions to start making radical improvements.

I’ve been very interested in web server performance because it is the first leg of the web page’s journey to the end user. The speed of execution at the server level is capable of making or breaking the user’s experience by controlling the amount of ‘lag time’ between the web page request and visible activity in the web browser. We want our server to send page data as immediately as possible so the browser can begin rendering it and downloading supporting files.

Not long ago, I described my web stack and explained why I moved away from the “safe” Apache server solution in favour of nginx. Since nginx doesn’t have a PHP module I had to use PHP’s FastCGI (PHP FPM) server with nginx as a reverse proxy. Additionally, I used memcached to store sessions rather than writing to disk.

Here are the configuration steps I took to realize this stack:

1. Memcached Sessions
Using memcached for sessions gives me slightly better performance on my Rackspace VM because in-memory reading&writing is hugely faster than reading&writing to a virtualized disk. I went into a lot more detail about this last April when I wrote about how to use memcached as a session handler in PHP.

2. PHP FPM
The newest Ubuntu distributions have a package php5-fpm that installs PHP5 FastCGI and an init.d script for it. Once installed, you can tweak your php.ini settings to suit, depending on your system’s configuration. (Maybe we can get into this another time.)

3. Nginx
Once PHP FPM was installed, I created a site entry that would pass PHP requests forward to the FastCGI server, while serving other files directly. Since the majority of my static content (css, javascript, images) have already been moved to a content delivery network, nginx has very little actual work to do.


server {
listen 80;
server_name sitename.com www.sitename.com;
access_log /var/log/nginx/sitename-access.log;
error_log /var/log/nginx/sitename-error.log;
# serve static files
location / {
root /www/sitename.com/html;
index index.php index.html index.htm;

# this serves static files that exists without
# running other rewrite tests
if (-f $request_filename) {
expires 30d;
break;
}

# this sends all-non-existing file or directory requests to index.php
if (!-e $request_filename) {
rewrite ^(.+)$ /index.php?q=$1 last;
}
}

location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /www/sitename.com/html$fastcgi_script_name;
include fastcgi_params;
}
}

The fastcgi_param setting controls which script is executed, based upon the root path of the site being accessed. All of the requests parameters are passed through to PHP, and once the configuration is started up I didn’t miss Apache one little bit.

Improvements
My next step will be to put a varnish server in front of nginx. Since the majority of my site traffic comes from search engine results where a user has not yet been registered to the site or needs refreshed content, Varnish can step in and serve a fully cached version of my pages from memory far faster than FastCGI can render the WordPress code. I’ll experiment with this setup in the coming months and post my results.

Tags: , , , , ,

4 Responses to “Setting up WordPress with nginx and FastCGI”

  1. Jamie says:

    Rather than going through TCP traffic, I suggest the following change:

    fastcgi_pass 127.0.0.1:9000;

    Becomes:

    fastcgi_pass unix:/tmp/php5-fpm.sock;

  2. […] friend and former colleague introduced me to nginx a while back with his blog about Setting up WordPress with nginx and FastCGI.  This is quite useful for understanding the nginx configuration for a virtual host that requires […]

  3. Constantinos says:

    Hey,
    Im running a wordpress installation on a lemp setup ubuntu 12,04lts
    1 got 750 mb memory on my system.

    Every time i restart php and ngonx services, wordpress consumes about 100 mb memory. In some hours it consumed all the memory of my system. And its just a buisiness site with no traffic. Is this regular? I want to host more wordpress installations on this setup but im afraid cause of this memory consumtion.
    Is there anything i can do?

  4. Mike says:

    100-200mb per site sounds about right. Using up all of the memory could indicate a configuration issue (too many workers/PHP processes) or a memory leak. You should be able to run 5-6 moderately-trafficked sites on a machine with 750mb ram.

    By itself memory consumption is not a huge problem unless is it having a visible effect on your site’s load times. The software is designed to use the memory it has available, which includes swap and cached memory, not just physical ram.

    Some things to check:

    * MySQL processes – this should be set low in your case, otherwise your database will hog all of your memory
    * Script execution time – Limit to 2-3 seconds in your php.ini. By default this value is up at 30 or 60 seconds. No one is going to wait for a web page that loads this slowly, so setting a low threshold will save you from bottlenecked scripts slowing the rest of your site down
    * Memory limit – Also should be kept low on a system like this

Leave a Reply