Apache is not adequate in restricted environment
As I said earlier, on a HostIcan VPS, my applications were running unbearably slow and erratically. I was determined to get it right even with the hard RAM limitation. BTW, I found VPSLink offers the most affordable package and reliable servers, use the referral code CSR42P to get a 10% lifetime discount.
Most Wordpress blog would get an F rating on Yahoo’s YSlow, a Firefox plug-in, for having too many HTTP requests (averaging 20~30 image, CSS and Javascripts). With the loose collaboration nature of open-source development, the number of HTTP requests will only increase with more plug-in and pretty themes. The Javascript driven Web 2.0 demands even more HTTP requests.
Apache default setup performs particularly bad in such a situation. If your applications are heavily PHP based, it’s not recommended (not all PHP modules is thread-safe) to run thread-based MPM (Multi-Processing Module, such as Worker MPM). You’re left with multi-process based prefork MPM. Each prefork process can grow to 250MB using 15~70MB RAM. PHP opcode cache occupies some 64MB. 15~20 Apache processes will take up over 300MB RAM. And you want to leave room to MySQL and have spare RAM for other memory hungry scripts. Remember I only have 512MB RAM on my VPS. If Apache process runs in HTTP/1.1 keep-alive mode, the server becomes very irresponsive when there’re many concurrent accesses.
“So I’m doomed!” thought I.
Lighttpd rocks with keep-alive
It’s at those moment of desperation, I found Lighttpd (pronounced Lighty). Lighty has a single-thread asynchronous IO architecture. Because of the asynchronous nature, an idle connection does not lock down a process or a thread as in Apache. This is perfect for keep-alive connections. In fact, Lighttpd scales very well with large number of concurrent requests.
I did a little benchmarking. For a PHP/MySQL script which generates a 40KB HTML page, 50 concurrent clients ( ab –n5000 –c50 [–k] )
- Apache prefork MPM: 200 requests/second
- Lighttpd: 204 r/s
- Apache: 244 r/s
- Lighttpd: 256 r/s
HTTP/1.1 Keep-alive makes a 25% performance difference.
Lighty is good, leaky is bad
With Lighty in hand, it seems I found a solution. Migrating from Apache to Lighttpd is pretty simple. It’s easier to run Lighttpd as User: apache and Group: apache, so that php-cgi won’t have permission problem with the existing PHP session directory. The only problem exists with scripts that rely on .htaccess to define mod_rewrite rules, such as Wordpress. Lighty mod_rewrite rules can only be implemented in configuration file. For Wordpress, you need to define the following:
$HTTP["host"] =~ "(^|\.)MyDomain\.com$" {
server.document-root = "/var/www/html/MyDomain"
server.error-handler-404 = "/index.php"
}
My FastCGI configuration is as follows:
fastcgi.server = ( ".php" =>
( "localhost" =>
(
"socket" => "/var/run/lighttpd/php-fastcgi.socket",
"bin-path" => "/usr/bin/php-cgi",
"bin-environment" =>
(
"PHP_FCGI_CHILDREN" => "32",
# terminate php process after the number of requests
# being processed, in case Php leaks memory
"PHP_FCGI_MAX_REQUESTS" => "1000"
),
"bin-copy-environment" => ( "PATH", "SHELL", "USER" ),
"min-procs" => 1,
"max-procs" => 1,
"max-load-per-proc" => 8,
"idle-timeout" => 50,
# Fix PATH_INFO for PHP scripts that rely on it (like Wordpress).
"broken-scriptfilename" => "enable"
) ) )
The number of php processes = max-procs * (PHP_FCGI_CHILDREN + 1).
There are max-procs watcher processes which do not handle requests and max-procs * PHP_FCGI_CHILDREN real php backends which serve requests. If you are using an opcode cache such as eAccelerator, XCache or APC it’s advisable to keep max-procs at a very low number (1 is perfectly fine) and raise PHP_FCGI_CHILDREN instead. Those opcode caches will create a separate memory space for each parent process, otherwise. If you leave max-procs at 4, you’ll end up with four separate opcode memory cache segments.
I also bumped up the APC cache size from 32MB to 64MB (apc.shm_size=64 in /etc/php.d/apc.ini) and can run 32 PHP FastCGI processes using 210MB RAM. After that, my sites are running at a lightening speed.
While everything is rosy, I was in dismay seeing Lighty bloated from 3MB to 100MB over night. Well, there’s a memory leak in Lighttpd 1.4.18. It took over a year for someone to fix it in 1.4.20. That’s probably why Redhat EL5 doesn’t include Lighty.
I took the lighttpd-1.4.20-1.fc10.src.rpm from Fedora 10 and rebuild it in Fedora 8. Now everything runs smoothly. Download the RPMs if you want.
How to enjoy this labour of love?
Looking back this quest for running busy websites on a budget VPS, it’s not an easy route. Lighty document is rather well “lighty”, in drastic contrast to Apache. Every time there’s a glitch, you have to Google for other people’s pearls of wisdom.
When I turn on Lighty RRDTool performance graphs, it is rather enjoyable knowing that my server can handle a substantial load at a fast speed.
Here’s two useful commands. To find out the RAM usage on your VPS.
Look for “-/+ buffers/cache: 179724 344740″
To find out a process sizer,
- % top -bn 1 | grep lighttpd
Read Part 1: Choose the right VPS to host your busy websites
Related posts
Tags: Apache, apache processes, asynchronous nature, benchmarking, C50, concurrent accesses, concurrent clients, concurrent requests, configuration, Default Setup, desperation, Driven Web, FastCGI, FCGI, Fedora, Firefox, hostican, Javascript, javascripts, Lifetime Discount, lighttpd, loose collaboration, memory, MySQL, Mysql Script, open source development, PHP, php mysql, prefork, Redhat, Referral Code, single thread, VPS, wordpress, Yahoo, YSlow