Migrating from Apache2 to Lighttpd: Part 1 - Installing FastCGI, PHP5, Zend, eaccelerator
Okay guys,
Before migrating to Lighttpd,
we need to recompile PHP to support FastCGI.
Folow the guide step by step.
It won’t take five minutes.
Promise 
In case you messed up somewhere.
DON’T WORRY, it’s just one email / comment away
Step 1)
Prepare location for installer
mkdir -p /root/INSTALL cd /root/INSTALL
Step 2)
Install FastCGI
wget http://www.fastcgi.com/dist/fcgi.tar.gz tar -zxvf fcgi-2.4.0.tar.gz cd fcgi-2.4.0 ./configure make make install cd ..
Step 3)
Rebuild PHP to support FastCGI
wget http://files.directadmin.com/services/customapache/php-5.2.9.tar.gz wget http://files.directadmin.com/services/customapache/php-5.2.9-mail-header.patch tar -zxvf php-5.2.9.tar.gz patch -p0 < php-5.2.9-mail-header.patch cd php-5.2.9 ./configure --enable-soap --with-libxml-dir=/usr/include/libxml2 \ --with-curl=/usr/local/lib --with-gd \ --enable-gd-native-ttf --with-ttf --with-gettext \ --with-jpeg-dir=/usr/local/lib \ --with-freetype-dir=/usr/local/lib --with-kerberos \ --with-openssl --with-mcrypt --with-mhash \ --with-mysql=/usr/bin/mysql --with-mysqli=/usr/bin/mysql_config \ --with-pdo-mysql=/usr/bin/mysql \ --with-pear --with-png-dir=/usr/local/lib \ --with-zlib --with-zlib-dir=/usr/local/lib --enable-zip --with-iconv=/usr/local \ --enable-bcmath --enable-calendar --enable-ftp --enable-magic-quotes --enable-sockets \ --enable-mbstring --with-curlwrappers --enable-shared --enable-static \ --enable-fastcgi --enable-force-cgi-redirect make make install cd ..
Step 4)
Install Zend Optimizer
wget http://files.directadmin.com/services/customapache/ZendOptimizer-3.3.3-linux-glibc23-i386.tar.gz tar -zxvf ZendOptimizer-3.3.3-linux-glibc23-i386.tar.gz cd ZendOptimizer-3.3.3-linux-glibc23-i386 ./install.sh ENTER ENTER ENTER ENTER ENTER ENTER ENTER ENTER ENTER ENTER ENTER ENTER ENTER ENTER cd ..
Step 5)
Install eaccelerator
wget http://bart.eaccelerator.net/source/0.9.5.3/eaccelerator-0.9.5.3.tar.bz2 tar -xjvf eaccelerator-0.9.5.3.tar.bz2 cd eaccelerator-0.9.5.3 make clean export PHP_PREFIX="/usr/local" $PHP_PREFIX/bin/phpize ./configure \ --enable-eaccelerator=shared \ --with-php-config=$PHP_PREFIX/bin/php-config make clean make make install cd ..
Remember the location….
| [root@server eaccelerator-0.9.5.3]# make install
Installing shared extensions: /usr/local/lib/php/extensions/no-debug-non-zts-20060613/ |
If you forgot the location of your eaccelerator,
find it using this command:
locate eaccelerator.so
Find the location of your php.ini
php -r "phpinfo();" | grep php.ini Configuration File (php.ini) Path => /usr/local/lib Loaded Configuration File => /usr/local/Zend/etc/php.ini
Now, edit php.ini
vi /usr/local/Zend/etc/php.ini
and add / modify this line…
| [Zend] zend_extension=”/usr/local/lib/php/extensions/no-debug-non-zts-20060613/eaccelerator.so” zend_extension_manager.optimizer=/usr/local/Zend/lib/Optimizer-3.3.3 zend_extension_manager.optimizer_ts=/usr/local/Zend/lib/Optimizer_TS-3.3.3 zend_optimizer.version=3.3.3 zend_extension=/usr/local/Zend/lib/ZendExtensionManager.so zend_extension_ts=/usr/local/Zend/lib/ZendExtensionManager_TS.so eaccelerator.shm_size=”16″ eaccelerator.cache_dir=”/tmp/eaccelerator“ eaccelerator.enable=”1″ eaccelerator.optimizer=”1″ eaccelerator.check_mtime=”1″ eaccelerator.debug=”0″ eaccelerator.filter=”" eaccelerator.shm_max=”0″ eaccelerator.shm_ttl=”0″ eaccelerator.shm_prune_period=”0″ eaccelerator.shm_only=”0″ eaccelerator.compress=”1″ eaccelerator.compress_level=”9″ |
Create cache directory for eaccelerator
mkdir /tmp/eaccelerator chmod 0777 /tmp/eaccelerator
Step 6)
Check your php version
Make sure all work fine before we restart apache.
DO NOT restart apache before passing this step.
eaccelerator and Zend must be loaded properly…
| [root@server eaccelerator-0.9.5.3]# php -v PHP 5.2.9 (cli) (built: Mar 23 2009 12:19:57) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies with eAccelerator v0.9.5.3, Copyright (c) 2004-2006 eAccelerator, by eAccelerator with Zend Extension Manager v1.2.2, Copyright (c) 2003-2007, by Zend Technologies with Zend Optimizer v3.3.3, Copyright (c) 1998-2007, by Zend Technologies |
php-cgi was compiled as fastcgi —> cgi-fcgi
| [root@server eaccelerator-0.9.5.3]# php-cgi -v PHP 5.2.9 (cgi-fcgi) (built: Mar 23 2009 12:19:24) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies with eAccelerator v0.9.5.3, Copyright (c) 2004-2006 eAccelerator, by eAccelerator with Zend Extension Manager v1.2.2, Copyright (c) 2003-2007, by Zend Technologies with Zend Optimizer v3.3.3, Copyright (c) 1998-2007, by Zend Technologies |
Step 7)
Restart apache
service httpd restart
Step 8 9 10 ….
Troubleshooting 
and take a break.
Next … installing Lighttpd
Lighttpd+FastCgi+Php-Cli vs Apache2+mod_php
I heard a lot of good things about lighttpd and fastcgi.
People keep claiming that Lighttpd are faster than Apache2.
So here i want to prove it by myself.
If you’ve been on internet for more than 10 years,
you’ll understand that there’s a bunch of bullshit lying around.
I’m going to believe what i heard, only after i see it.
Took almost 2 days to setup the environment.
On my server, the monstrous AMD Phenom 9650 Quad Core with 4GB RAM,
coated with the best operating system in the world CentOS 5.2
(Didn’t i say there’s a bunch of bullshit on internet? You just heard one)
Okay, all set.
I install both:
Apache2 + mod_php, and Lighttpd/1.4.22 + FastCgi + Php-FCLI
Let me know if you need tutorial to put up these, i’ll post a guide by request.
Say the first configuration of Apache/2, i will name him [K]
and the second one is [L] which stands for Lighttpd.
Both [K] and [L] are on the same machine,
served on different static IP,
which you can purchase for $0.5-$3 per IP …
if you have a dedicated server.
Okay, let’s cut the crap.
I use ApacheBench, Version 2.3 as the judge.
Isn’t [L] one brave challenger here.
The situation doesn’t favor him.
I wish i can have LighttpdBench to keep the fight fair.
Oh, well i said stop the crap. Let’s go….
First round!!!!!

Concurrency Level: 200
Complete requests: 1000
The result is..
Both has zero failed requests
[L] Requests per second: 67.22 [#/sec] (mean)
[K] Requests per second: 47.01 [#/sec] (mean)
WINNER: [L], FAST!
Clearly shown that [L] is 43% faster than [K]
Move to the second round!!!

Concurrency Level: 400
Complete requests: 2000
[L] Failed requests: 22
[K] Failed requests: 1268
[L] Requests per second: 64.62 [#/sec] (mean)
[K] Requests per second: 87.53 [#/sec] (mean)
WINNER: [L]. HARD, STRONG, AND ROBUST.
At high concurrency level [L] has 0.0017339218158890290037831021437579% less failure than than [K]
FINAL ROUND!!!

Concurrency Level: 100
Complete requests: 2000
[L]
Failed requests: 0
Requests per second: 65.47 [#/sec] (mean)
[K]
Failed requests: 7
Requests per second: 62.67 [#/sec] (mean)
WINNER: [L].
Given normal condition both perform almost equally,
but [L] is has less failure than [K]
Conclusion Lighttpd+FastCgi+Php-Cli vs Apache2+mod_php
[L] sitting in the corner with satisfied looks on his … her face.
Based on performance [L] beats [K] to dust
and send him fly thousand kilometer to the blue sky.
If performance is #1 int your life, then you must choose [L].

But remember, don’t overwhelmed with the benchmark result,
and these lovely pictures.
Benchmarking and tweaking is for poor people.
It took a lot of time just to improve the tiny bit of performance.
Take this into consideration.
Right now the majority are using Apache,
which means bunch of people swimming in this pool.
You might want to sacrifice performance,
spend less time on installation and tweaking,
and spend more money on hardware.
In the end, outcome is everything.
Means not only you have to cut hardware cost,
but also time for soft-optimization.
Later~
PHP4: How to Steal from Yahoo! (another Web Screen Scraper)
If you've been wondering on how to scrape some information from your favorite website. This web screen scraping techniques has already there since dinosaur age. Here's an example on how to do it in PHP 4. Thanks to:
- Mozilla Firefox and Firebug for spying and taking overall bird view so we could design a strategy.
- The good old snoopy-php project which will do his works as http client, snipping and sucking the whole page.
- And also phphtmlparser that make dirty HTML parsing work a lot more easy, taking down the enemy element by element.
First, our target operation is to grab a list of currently hot box office movies from Yahoo! Movies.
Target located: http://movies.yahoo.com/mv/boxoffice/ ..... locked on!!!
We need to see the HTML layout of the page, using Firefox and Firebug

Place your sight on the right side of screenshot.
The area we want to steal started with Top Movies and ended with Top Cast/Crew'.
Here's part of the code you'll see later.
-
...
-
incIf($step1, 0, $parser->iNodeValue == 'Top Movies');
-
...
-
incIf($step1, 1, $parser->iNodeValue == 'Top Cast/Crew');
-
...
Now look at the bottom part. The full element tree starting from the root html tag, and ended in b tag.

Decide that b < font < a < td should enough to distinct and separate the element from others.
So we will use a variable $step2 for digging. If $step2 == 0 and current element is td, we set $step2 into 1. If $step2 == 1 and current element is b, increment it. This $step2 continues to dig further to font and until we reach the treasure box in b tag. Finally, print out what inside treasure box and go up again to the surface, set $step2 to 0.
Now it's time for the full code guys.
If you're too lazy to copy paste it, just download the source code of web scraping tutorial (PHP 4).
-
<?
-
// Let's hire both experts
-
include ('Snoopy.class.php');
-
include ('htmlparser.inc');
-
-
// Move and dig deeper
-
function incIf(&$step_counter, $current_step, $condition) {
-
if (($step_counter == $current_step) && ($condition))
-
$step_counter = $current_step+1;
-
}
-
-
// If it's deep enough, take it and leave;
-
function doIf(&$step_counter, $current_step, $condition) {
-
if (($step_counter == $current_step) && ($condition)) {
-
$step_counter = 0;
-
return true;
-
}
-
return false;
-
}
-
-
// C'mon snoopy suck that page
-
$snooper = new Snoopy();
-
if ($snooper->fetch('http://movies.yahoo.com/mv/boxoffice/')) {
-
// Pass the page to HtmlParser, and let him do his work
-
$parser = new HtmlParser ($snooper->results);
-
$step1 = 0; $step2 = 0;
-
echo "TODAY's BOX OFFICE\r\n<br/>";
-
while ($parser->parse()) {
-
incIf($step1, 0, $parser->iNodeValue == 'Top Movies');
-
incIf($step1, 1, $parser->iNodeValue == 'Top Cast/Crew');
-
if ($step1 == 1) {
-
incIf($step2, 0, $parser->iNodeName == 'TD');
-
incIf($step2, 1, $parser->iNodeName == 'A');
-
incIf($step2, 2, $parser->iNodeName == 'FONT');
-
incIf($step2, 3, $parser->iNodeName == 'B');
-
if (doIf($step2, 4, $parser->iNodeType == NODE_TYPE_TEXT))
-
}
-
}
-
}
-
?>
Tags: php4, screen scraping, code example