Oct 152011
 

This is an article of mine, already published on wazi

Do you have problems serving more than two pages per second on your WordPress or Drupal blog? Do the sites of your competitors serve pages faster than yours? Their secret weapon may be a different web server and PHP combo than Apache and mod_php. But don’t worry – you can turn to one of these alternative solutions too, and improve your web server throughput without upgrading your hardware resources.

First, some background. In general an HTTP or web server sends browser clients a requested page, usually in HTML code, or a page dynamically created with a language such as PHP, one of the most common programming languages for web pages. The PHP scripting language resembles JavaScript, Java, and Perl, all of which share a common ancestor, the C programming language. If you need to embed dynamic text, such as the result of queries on databases, into static text, you’ll find PHP extremely useful.




One of the oldest extant web servers, and the most popular, Apache, has come a long way since it was released in 1995. Technically, Apache consists of a daemon on Unix or a service under Microsoft Windows, which, depending on the settings in a configuration file, provides access to one or multiple sites (virtual hosts), manages security features, and can accommodate extensions to serve active or dynamic pages, such as PHP or, for Java developers, it allow to communcate with Tomcat.

An Apache HTTP server can be configured to work in either of two ways. Multi-Processing Module Prefork (MPM prefork) implements a non-threaded, pre-forking web server that is appropriate for sites that need to avoid threading for compatibility with non-thread-safe libraries. Typically, any non-trivial Apache module (such as mod_php, a module that Apache can load to serve PHP dynamic pages) has some sort of non-thread-safe library or has non-thread-safe code in it, so when in doubt use the MPM prefork. In many distribution, including Debian and Red Hat, when you install mod_php the system automatically installs the MPM prefork version of the Apache package. MPM prefork is also the best MPM for isolating each request, so that a problem with a single request will not affect any other. A request generally corresponds to a single process on a Linux server.

By contrast, Multi-Processing Module Worker (MPM worker) implements a hybrid multi-process multi-threaded server. By using threads to serve requests, it is able to serve a large number of requests with fewer system resources than a process-based server. However, it retains much of the stability of a process-based server by keeping multiple processes available, each with many threads.

Alternative HTTP servers

Apache powers more than 70% of websites today, but new alternatives are gaining market share. Apache is a reliable server, but it takes considerable memory to run. In some situations other web servers can perform better. The best-known alternative open source HTTP servers are lighttpd, nginx, and Cherokee.

webservers

Market Share for Top Servers Across All Domains from August 1995 to July 2011 (Source: Netcraft)

lighttpd is a secure, fast, compliant, and flexible web server that’s optimized for high-performance environments. It has a very low memory footprint compared to other web servers, and usually a lower CPU load. It has an advanced feature set that includes load-balanced FastCGI, CGI, Auth, Output-Compression, URL-Rewriting, SSL, and more.

nginx is an HTTP server and mail proxy server. It has been running for more than two years on many heavily loaded Russian sites, and it has become more popular in the rest of the world, to the point where today it’s used by 6.5% of all websites.

Cherokee is a fast, flexible, and easy-to-configure web server that supports FastCGI, SCGI, PHP, CGI, TLS and SSL encrypted connections, virtual hosts, authentication, on-the-fly encoding, load balancing, Apache compatible log files, and more. It also provides an easy-to-use web configuration interface that allows you to configure the server from top to bottom without editing a text configuration file.

If you’re building a new site from scratch, which web server platform should you use? Each of these servers has pros and cons, as we’ll see below. You must weigh your expected needs against the features and abilities of each server, and also your knowledge of each. Many people know Apache well and use it for every site. This is not a bad idea, but if you are planning a site with particular characteristics then another web server may be better.

Asynchronous vs. Synchronous

Web servers can be divided into two categories, asynchronous (nginx and lighttpd) and synchronous (Apache and Cherokee). The main advantage of the asynchronous approach is scalability. In a synchronous or process-based server, each simultaneous connection requires its own thread, which incurs significant overhead. An asynchronous server, on the other hand, is event-driven and handles requests in a single (or at least, very few) threads.

While process-based servers can often perform on par with asynchronous servers under light loads, under heavier loads they usually consume far too much RAM, which significantly degrades performance. Also, they degrade much faster on less powerful hardware or in resource-restricted environments such as virtual private servers (VPS).

Mod_php vs. FastCGI

The most common method to process PHP pages under Apache is via mod_php, the PHP module. mod_php is loaded at server startup, and processes the PHP pages inside one parent process, but every process that is forked from the parent (we are in synchronous mode) must load the full stack, using more memory. To avoid this, you can configure your web server to process PHP via an external process. The FastCGI daemon processes requests and returns results to the web server, in contrast to classic CGI, where a shell process is forked from an Apache child, which is less efficient and slow. PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some useful features for sites of any size, especially busier sites.

PHP-FPM is intended mainly for websites burdened by numerous HTTP requests. It can launch multiple pools of fastcgi processes listening on separate ports to meet the demands of multi-domain virtual hosting environments. It also offers:

  • Advanced process management with graceful stop/start
  • The ability to start workers with different uid/gid/chroot/environments and different php.ini settings (replaces safe_mode)
  • Stdout and stderr logging
  • Emergency restart in case of accidental opcode cache destruction
  • Accelerated upload support
  • Support for a “slowlog” that logs pages that take too much time to complete

You can use PHP-FPM as a back end to any web server and not be bound anymore to Apache in MPM-prefork mode. Another advantage has to do with standard mod_php, which run in a process that takes up an usually large amount of memory, because it contains not only PHP but also all the other Apache modules. If PHP is run in a separate process, that process can have a shorter lifetime, and quickly pass results back to Apache when PHP is done.

Nginx plus PHP-FPM

Sysadmins who know Apache backwards and forwards might want to try an alternative approach for a new web server, both to better meet site visitors’ needs and to keep their technical skills fresh. The combination of nginx with PHP-FPM is becoming popular in environments that have low amounts of memory available (VPS usually) or big sites that must process many concurrent requests. It’s a great substitute for mod_php in Apache.

If you want to try this configuration yourself, here are a few tips. Just as a small note – in Debian I suggest using the dotdeb.org repository to get a recent version of these packages. For CentOS you can add the IUS repository and install these packages with yum:

#EPEL
wget http://dl.iuscommunity.org/pub/ius/stable/Redhat/5/x86_64/epel-release-1-1.ius.el5.noarch.rpm
#IUS Community
wget http://dl.iuscommunity.org/pub/ius/stable/Redhat/5/x86_64/ius-release-1.0-6.ius.el5.noarch.rpm
#Install repos
rpm -Uvh epel-release-1-1.ius.el5.noarch.rpm ius-release-1.0-6.ius.el5.noarch.rpm

vi /etc/yum.repos.d/ius.repo
#Comment out this line:
mirrorlist=http://dmirr.iuscommunity.org/mirrorlist?repo=ius-el5&arch=$basearch
#Add this line:
baseurl=http://dl.iuscommunity.org/pub/ius/stable/Redhat/5.5/$basearch

#IUS PHP 5.3 packages are prefixed with "php53u" to avoid name clashes
yum install php53u-fpm 

#Use EPEL nginx. 
yum install nginx

PHP-FPM Configuration

PHP-FPM’s main configuration file, usually located in /etc/php5/fpm/php-fpm.conf, lets you set up the generic configurations for all pools. A pool in nginx is a set of processes that serve one or more virtual host; each pool has a number of initial processes and a maximum number. The processes share the same uid and gid and database connections. Usually you can leave this configuration file untouched and just create a file in /etc/php5/fpm/pool.d/YOURPOOL_NAME.

Here’s a model config file setup for a small machine – one with less than 1024MB of RAM.
In this example I’ve called my pool www-linuxaria:

; Start a new pool named 'www'.
; the variable $pool can we used in any directive and will be replaced by the
; pool name ('www' here)
[www]

; The address on which to accept FastCGI requests.
listen = 127.0.0.1:9000

; Unix user/group of processes - put your webserver user/group here
user = www-data
group = www-data

; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes to be created when pm is set to 'dynamic'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
pm.max_children = 20

; The desired minimum number of idle server processes.
pm.min_spare_servers = 2

; The desired maximum number of idle server processes.
pm.max_spare_servers = 10

; The number of requests each child process should execute before respawning.
; This can be useful to work around memory leaks in third-party libraries. 
pm.max_requests = 500

; The timeout for serving a single request after which the worker process will
; be killed. 
request_terminate_timeout = 30

Optionally you can activate these options:

; The URI to view the FPM status page. If this value is not set, no URI will be
; recognized as a status page.
pm.status_path = /status

; The ping URI to call the monitoring page of FPM. If this value is not set, no
; URI will be recognized as a ping page. This could be used to test from outside
; that FPM is alive and responding.
ping.path = /ping


Nginx Configuration

The main nginx configuration file is usually located in /etc/nginx/nginx.conf. Below are some suggested configuration directives for the same small machine with less than 1024MB of RAM:

#user and group of Nginx processes
user       www www;

#A worker process is a single-threaded process.
#If Nginx is doing CPU-intensive work such as SSL or gzipping and you have two or more CPUs/cores, you may set 
#worker_processes to be equal to the number of CPUs or cores. In this example we have four cores.
worker_processes  4;

#Generic error log for the web server
error_log  /var/logs/nginx/error.log;

#Location of your pid file
pid        /var/run/nginx.pid;

#Activate Events module
events {

#The worker_connections and worker_proceses from the main section allows you to calculate maxclients value:
#max_clients = worker_processes * worker_connections 
        worker_connections 768;
}

The files above provide generic configurations for all your sites. You should also have a file for every active site. Usually I give such a file the full name of the site; for example, on my Debian server I have the file /etc/nginx/sites-enabled/linuxaria.com, with settings like this:

server {

#The listen directive tells nginx where to listen in ipv4 and ipv6 for incoming connections.
    listen 80;
    listen [::]:80 ipv6only=on;

#Server name is your web server URL.
    server_name www.linuxaria.com linuxaria.com;

#root specifies the document root for requests.
    root /srv/www/linuxaria.com/public_html;

    ...

#Inside this location you can see how all .php files are processed. 
#We give the address of the php-fpm server (localhost:9000).
    location ~ \.php$ {
                include /etc/nginx/fastcgi_params;
                fastcgi_pass  127.0.0.1:9000;
                fastcgi_index index.php;
                fastcgi_param  SCRIPT_FILENAME  /srv/www/linuxaria.com/public_html$fastcgi_script_name;

These files should help you set up basic service with nginx and PHP-FPM. If you are moving from Apache to nginx the most difficult things to “convert” are usually the rewrite rules and .htaccess. Look at the official nginx documentation wiki and use this site to automatically convert your Apache .htaccess file to nginx rules.

Conclusions

Of course nginx with PHP-FPM is only one approach to serving PHP pages quickly. Many possible combinations of HTTP servers, cache servers, and back ends are available for you to try. If you’re not sure which ones might suit you, you can try asking the experts at the nginx forum, nginx planet, or nginx IRC channel, or searching for case studies. Some useful guides include:

Popular Posts:

Flattr this!

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)

*