Hope for the best, prepare for slashdot

July 8, 2008 – 12:31 am

You have a brand new wordpress blog. How fast is it ? It’s supposed to be fast, isn’t it ? Lighttpd is dead fast, php is fast, mysql is fast.

So let’s try it with ApacheBench:

ab -n 1000 http://libreamoi.com/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/
Benchmarking libreamoi.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Finished 1000 requests
Server Software:        lighttpd/1.4.19
Server Hostname:        libreamoi.com
Server Port:            80
Document Path:          /
Document Length:        20504 bytes
Concurrency Level:      1
Time taken for tests:   295.536900 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      20725000 bytes
HTML transferred:       20504000 bytes
Requests per second:    3.38 [#/sec] (mean)
Time per request:       295.537 [ms] (mean)
Time per request:       295.537 [ms] (mean, across all concurrent requests)
Transfer rate:          68.48 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:   290  294  19.9    293     741
Waiting:      222  225  15.0    224     536
Total:        290  294  19.9    293     741
Percentage of the requests served within a certain time (ms)
  50%    293
  66%    294
  75%    294
  80%    294
  90%    295
  95%    296
  98%    298
  99%    323
 100%    741 (longest request)

Ouch, only 3.38 requests per second I hoped for more ! That’s definitely not slashdot ready !

By the way my server is a Celeron at 2.66 GHz with 1Go of ram so it’s nothing great but not that bad either.

So what if I get slashdotted and get a thousand hit per second? Well the first 100 visitors will see my article all right. And then for about 1 day my site will be unusable while I could have won millions of dollars with adsense. That’s not what you want is it ?

That’s why you need varnish. Varnish is a cool reverse proxy. That will make your blog real fast. How fast ? Well we’ll see after installing it. So remember I have and ubuntu server, which mean apt-get for installing stuff.

$ apt-get install varnish

Run that as root and it will install varnish and run it. Is it finished yet ? No. Lighttpd is on port 80 so varnish can’t have taken it. It didn’t take it cause by default varnish run on port 6081.

You can change that by editing /etc/default/varnish and putting

VARNISH_LISTEN_PORT=80

Now you need to edit the configuration of lighttpd to run on another port, I chose port 81, so uncomment the following line in /etc/lighttpd/lighttpd.conf

server.port               = 81

We now need to edit the configuration file of varnish, varnish uses its own configuration syntax called vcl for varnish configuration language and which is compiled to c. So open /etc/varnish/vcl.conf

# This is a basic vcl.conf file for varnish.
 # Modifying this file should be where you store your modifications to
 # varnish. Settnigs here will override defaults.
backend default {
 set backend.host = "127.0.0.1";
 set backend.port = "80";
 }
sub vcl_recv {
 if (req.request == "POST") {
 pipe;
 }
# force lookup even when cookies are present
 if (req.request == "GET" && req.http.cookie) {
 lookup;
 }
 }
sub vcl_fetch {
 # force minimum ttl of 180 seconds
 if (obj.ttl < 180s) {
 set obj.ttl = 180s;
 }
}

This is the default debian configuration. So first change the backend port to 81 to match the lighttpd port. Then all is ready it will cache all http “GET” requests for 3 minutes. But it’s not perfect. If you keep the configuration like that all pages will be cached by varnish even when logged in as the admin. So it will cache some pages with “Log out” instead of “Log in”, and as the admin you will often see “Log in” when you are already logged in.

We could disable the cache when there is a cookie present, but wordpress puts on some crap cookies even when you are not logged in. So nothing would be cached.

The good solution is to add a little bit of vcl magic

if (req.http.cookie ~ "(comment_)|(wordpress_\w{32}=)") {
        pipe;
}

This small bit of magic need to be added before the “# force lookup even when cookies are present” comment, and it will match the cookie header in the request for the following regular expression “(comment_)|(wordpress_\w{32}=)” and will not cache the request if it matches. It matches if the user has posted a comment or if he is logged in.

By the way I used firecookie to see what cookies are present on web pages.

Now, Restart lighttpd and varnish

/etc/init.d/lighttpd restart && /etc/init.d/varnish restart

Your blog is now cached by varnish and should be much faster. You don’t believe me ? Let’s test it.

ab -n 1000 http://libreamoi.com/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/
Benchmarking libreamoi.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Finished 1000 requests
Server Software:        lighttpd/1.4.19
Server Hostname:        libreamoi.com
Server Port:            80
Document Path:          /
Document Length:        20504 bytes
Concurrency Level:      1
Time taken for tests:   0.531340 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      20806000 bytes
HTML transferred:       20504000 bytes
Requests per second:    1882.03 [#/sec] (mean)
Time per request:       0.531 [ms] (mean)
Time per request:       0.531 [ms] (mean, across all concurrent requests)
Transfer rate:          38239.17 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     0    0   0.0      0       0
Waiting:        0    0   0.0      0       0
Total:          0    0   0.0      0       0
Percentage of the requests served within a certain time (ms)
  50%      0
  66%      0
  75%      0
  80%      0
  90%      0
  95%      0
  98%      0
  99%      0
 100%      0 (longest request)

That’s a nice performance gain: 1882 requests per second ! That’s more than 500 times faster than before !

That’s probably slashdot proof.

[Edit: thank you Youenn for noticing the apache bench were actually hitting a 302 page ... cause I did it over localhost which was redirected to libreamoi.com so I did them again]

Post a Comment