Dec 16 2008
Speedy ride on a VPS with Lighttpd
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] )
- Without keep-alive:
- Apache prefork MPM: 200 requests/second
- Lighttpd: 204 r/s
- With keep-alive
- 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.
- lighttpd-1.4.20-1.fc8.i386.rpm
- lighttpd-debuginfo-1.4.20-1.fc8.i386.rpm
- lighttpd-fastcgi-1.4.20-1.fc8.i386.rpm
- lighttpd-mod_geoip-1.4.20-1.fc8.i386.rpm
- lighttpd-mod_mysql_vhost-1.4.20-1.fc8.i386.rpm
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.
- % free
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
Hi.
Is VPSLink down for you as well? Upon your recommendation I ordered from them a week ago or so. I can’t login to restart or do anything. It’s down.
Ema
[Reply]