The Case
In our case we want to reduce the load on a web server as well as optimize the performance for the website itself.
The website itself is mostly static so we can set the cache time to at least three hours.
Please keep in mind that using this guideline requires a mostly static page like "http://www.all2e.com" where the user isn't able to login on the eZ Publish public siteaccess. Otherwise using Varnish will be a lot harder.
By using the Varnish reverse Proxy we’ll be able to reduce the request made to the apache server, the Queries to the MySQL Database, as well as the overall performance of the web page due to Varnish is much faster in delivering content than apache or other proxies like Squid.
Therefore we’ll install the Varnish Reverse Proxy on the same physical server as the apache itself. After the installation we’ll have different url’s with which we may access the site.
The first ones are the cached Varnish version (http://www.all2e.com, http://all2e.com ),
the second one will be the normal url, which directly points to the apache server (http://nocache.all2e.com)
With this configuration it’s not necessary to do any changes (like Port changes) to the apache configuration itself. Varnish will just forward the request to the apache with the same domain name if the cache for the requested web page isn’t already present or if the page isn’t cachable.
The setup itself isn't very complex if you've once understood how varnish works. You can also have an abstract configuration file so the varnish cache is available for every website on the server instantly. But I'm trying to keep this guideline simple. If you've any question or need support feel free to contact us at http://www.all2e.com.
About Varnish
Varnish is a state-of-the-art, high-performance HTTP accelerator. It uses the advanced features in Linux 2.6, FreeBSD 6/7 and Solaris 10 to achieve high performance.
Some of the features include
- A modern design
- VCL - a very flexible configuration language
- Load balancing with health checking of backends
- Partial support for ESI
- URL rewriting
- Graceful handling of "dead" backends
- ...
Varnish is free software and is licensed under a modified BSD license.
For more information about Varnish visit: http://varnish.projects.linpro.no/
Requirements
- Varnish Source files
- a separate new IP address for Varnish already set up on the server
- installed "ncurses-dev" package (otherwise varnishstat and varnishtop won't be installed)
Setting up the DNS entry's
Set up your domain so that http://www.yourdomain.com and http://yourdomain.com point to the new IP address.
In this case we'll use http://www.all2e.com and http://all2e.com to point at the IP 217.115.149.8
Create a new subdomain called "nocache.yourdomain.com" which points to your normal Apache's IP address.
In our case it's nocache.all2e.com pointing to 87.230.58.81.
Don't forget to set up apache correctly so it listens also to the new subdomain.
This makes it easy to access the web page without any caches when you get in trouble.
Installing Varnish from Source
In our case we’ll install Varnish on a Debian based web server. Currently there’s no up to date package available for debian, so we’ll install Varnish from source and build a new start / stop script for debian.
~# cd /usr/local/src ~# wget http://dfn.dl.sourceforge.net/sourceforge/varnish/varnish-2.0.2.tar.gz ~# tar xvfz varnish-2.0.2.tar.gz ~# cd varnish-2.0.2 ~# ./configure --prefix=/usr/local \ --sysconfdir=/etc \ --localstatedir=/var/lib/ \ --mandir=/usr/share/man ~# make && make install
Creating a new user for Varnish
Set up the new system user for varnish:
~# adduser varnish Adding user `varnish' ... Adding new group `varnish' (1006) ... Adding new user `varnish' (1008) with group `varnish' ... Creating home directory `/home/varnish' ... Copying files from `/etc/skel' ... Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully Changing the user information for varnish Enter the new value, or press ENTER for the default Full Name []: varnish system user Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [y/N] y
Varnish system configuration
Copy the default Varnish configuration file form the sources to your local default configuration directory.
~# cp /usr/local/src/varnish-2.0.2/redhat/varnish.sysconfig /etc/default/varnish
To configure Varnish open the configuration file and set up the following configuration:
VARNISH_VCL_CONF=/etc/varnish/default.vcl
VARNISH_LISTEN_ADDRESS=217.115.149.8
VARNISH_LISTEN_PORT=80
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
VARNISH_MIN_THREADS=1
VARNISH_MAX_THREADS=1000
VARNISH_THREAD_TIMEOUT=120
VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin
VARNISH_STORAGE_SIZE=1G
VARNISH_TTL=120
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
-f ${VARNISH_VCL_CONF} \
-T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
-t ${VARNISH_TTL} \
-w${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
-u varnish -g varnish \
-s ${VARNISH_STORAGE}"
Change the owner of the storage file directory to the new varnish user:
~# chown -R varnish.varnish /var/lib/varnish/
Start / Stop Script for Debian
The default varnish start-stop-script (varnish.initrc) has been developed for redhat Distributions.
On debian based systems we’ll need to alter it so it fixes to our system.
I've already done that an made the script is available on our website: http://www.all2e.com/ so we may just download it here.
~# cd /etc/init.d ~# wget http://www.all2e.com/content/download/389/2092/version/1/file/varnish ~# chmod +x varnish
Setting up the Varnish configuration
Here’s an example on a simple Varnish configuration file, which can be used with eZ publish.
This configuration is for a single website and web server.
~# nano /etc/varnish/default.vcl
backend default {
.host = "87.230.58.81";
.port = "80";
}
sub vcl_recv
{
# normalize compression
if (req.http.Accept-Encoding){
if (req.http.Accept-Encoding ~ "gzip"){
set req.http.Accept-Encoding = "gzip";
}
elseif (req.http.Accept-Encoding ~ "deflate" ) {
set req.http.Accept-Encoding = "deflate";
}
else{
remove req.http.Accept-Encoding;
}
}
if (req.request == "POST")
{
pass;
}
# do not use Varnish when the user is authenticated
if (req.http.Cookie && req.http.Cookie ~ "is_logged_in" ) {
pass;
}
if (req.request == "GET")
{
lookup;
}
if (req.url ~ "\.(gif|jpg|jpeg|swf|css|js|flv|mp3|mp4|pdf|ico)$")
{
lookup;
}
/* Nirvana */
remove req.http.cookie;
}
sub vcl_fetch
{
if ( obj.http.Pragma ~ "no-cache"
|| obj.http.Cache-Control ~ "no-cache"
|| obj.http.Cache-Control ~ "private") {
pass;
}
/**
* Works with eZ Publish 3.*, 4.0.* with eZ Vlogin
*/
if (obj.http.Set-Cookie ~ "^eZSESSID.*=.*$")
{
set obj.http.X-Cookie = "Cookie removed";
remove obj.http.Set-Cookie;
}
}
sub vcl_hit
{
if (!obj.cacheable)
{
pass;
}
set obj.http.X-Cache = "Cache-Hit";
deliver;
}
Starting Varnish
Now we may test our setup for the first time:
~# /etc/init.d/varnish start
After starting varnish you should now see two processes running:
~# ps aux | grep "varnish"
root 8930 0.0 0.0 85580 1040 ? Ss 14:09 0:00 /usr/local/sbin/varnishd -P /var/run/varnish.pid -a 213.202.255.170:80 -f /etc/varnish/default.vcl -T 127.0.0.1:6082 -t 120 -w 1,1000,120 -u varnish -g varnish -s file,/var/lib/varnish/varnish_storage.bin,1G varnish 8931 0.3 0.0 1193596 1872 ? Sl 14:09 0:00 /usr/local/sbin/varnishd -P /var/run/varnish.pid -a 213.202.255.170:80 -f /etc/varnish/default.vcl -T 127.0.0.1:6082 -t 120 -w 1,1000,120 -u varnish -g varnish -s file,/var/lib/varnish/varnish_storage.bin,1G root 8946 0.0 0.0 2944 728 pts/1 S+ 14:09 0:00 grep varnish
If you run in trouble here and varnish doesn't start it's always a good idea to take a look at the syslog file
~#tail -f /var/log/syslog
If varnish has been started successfully you should see the something like:
Jan 16 19:30:02 ds87-230-58-81 /var/lib/varnish[13380]: child (13381) Started Jan 16 19:30:02 ds87-230-58-81 /var/lib/varnish[13380]: Child (13381) said Closed fds: 4 5 6 9 10 12 13 Jan 16 19:30:02 ds87-230-58-81 /var/lib/varnish[13380]: Child (13381) said Child starts Jan 16 19:30:02 ds87-230-58-81 /var/lib/varnish[13380]: Child (13381) said managed to mmap 1073741824 bytes of 1073741824 Jan 16 19:30:02 ds87-230-58-81 /var/lib/varnish[13380]: Child (13381) said Ready
within the syslog,
Runlevels
Finally we need varnish to be started at the different runlevels so the varnish reverse proxy automatically starts if the system is rebooted.
~# update-rc.d varnish defaults 40 Adding system startup for /etc/init.d/varnish ... /etc/rc0.d/K40varnish -> ../init.d/varnish /etc/rc1.d/K40varnish-> ../init.d/varnish /etc/rc6.d/K40varnish -> ../init.d/varnish /etc/rc2.d/S40varnish -> ../init.d/varnish /etc/rc3.d/S40varnish -> ../init.d/varnish /etc/rc4.d/S40varnish -> ../init.d/varnish /etc/rc5.d/S40varnish -> ../init.d/varnish
Adding cache headers to eZ Publish
Without adding cutom headers to the eZ Publish installation Varnish won't be able to cache the requested files and pages.
Add the following lines to the site.ini.append of the normal public siteaccess only:
[HTTPHeaderSettings] CustomHeader=enabled Pragma[/]= Cache-Control[/]=public, must-revalidate, max-age=10800 Expires[/]=10800
This will set the headers within eZ publish so that the reverse proxy is able to cache the site. In our case the cache will expire after 10800 seconds / 3 hours.
Don't forget to clear the caches within eZ Publish after altering the file.
Testing the installation
Header information
After this installation you should be able to access the the cached version of the site with the normal url:
If you take a look at the response headers you should see the following headers:
Server: Apache X-Powered-By: eZ Publish Expires: Fri, 16 Jan 2009 16:29:25 GMT Cache-Control: public, must-revalidate, max-age=10800 Last-Modified: Fri, 16 Jan 2009 13:29:25 GMT Served-by: www.all2e.com Content-Language: de-DE Vary: Accept-Encoding,User-Agent Content-Encoding: gzip Content-Type: text/html; charset=utf-8 Content-Length: 2650 Date: Fri, 16 Jan 2009 13:29:26 GMT X-Varnish: 998601438 Age: 0 Via: 1.1 varnish 200 OK
The normal installation without any Varnish caches should be available under the second url:
The headers here should be missing the Via 1.1 varnish and X-Varnish information
Date: Fri, 16 Jan 2009 16:07:19 GMT Server: Apache X-Powered-By: eZ Publish Expires: Fri, 16 Jan 2009 19:07:19 GMT Cache-Control: public, must-revalidate, max-age=10800 Last-Modified: Fri, 16 Jan 2009 16:07:19 GMT Served-by: nocache.all2e.com Content-Language: de-DE Vary: Accept-Encoding,User-Agent Content-Encoding: gzip Content-Length: 5575 Content-Type: text/html; charset=utf-8 200 OK
As you can see we have a
Cache-Control: public, must-revalidate, max-age=10800
header here.
If you access you Administrative siteaccess
http://www.all2e.com/all2e_admin
We may look at the Response Headers and see that we have the default Headers with no-cache settings
Server: Apache X-Powered-By: eZ Publish Expires: Mon, 26 Jul 1997 05:00:00 GMT Cache-Control: no-cache, must-revalidate Pragma: no-cache Last-Modified: Fri, 16 Jan 2009 16:13:41 GMT Served-by: www.all2e.com Content-Language: de-DE Vary: Accept-Encoding,User-Agent Content-Encoding: gzip Content-Type: text/html; charset=utf-8 Content-Length: 16809 Date: Fri, 16 Jan 2009 16:13:41 GMT X-Varnish: 998602468 Age: 0 Via: 1.1 varnish Connection: keep-alive 200 OK
The requested page is delivered through Varnish but not cached because of the Cache-Control header information.
Varnish Statistics
To check out if Varnish works in the way it should, you can connect to the Varnish control from the local machine using telnet.
~# telnet localhost 6082
Trying 127.0.0.1... Connected to localhost.localdomain. Escape character is '^]'.
If you type in "stats" now at the console
~# stats
you should see some cache statistics from Varnish
200 2766 12 Client connections accepted 156 Client requests received 124 Cache hits 5 Cache hits for pass 26 Cache misses
As you can see we have 124 cached hits out of 156 requests.
This indicates that Varnish is working as expected and directly delivers the content if the request is already cached.
Performance
After the installation is finished we may do some simple performance tests.
Browser Performance
Testing Browser loading times (Firefox using YSlow Plugin, normal DSL internet connection):
Without Varnish:
http://nocache.all2e.com/
Loading Time: 1.123 sec
With Varnish:
http://www.all2e.com/
Loading Time: 0.459 sec
Testing with apache Benchmark
~# ab -n1000 -c100 http://www.all2e.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 www.all2e.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: Apache
Server Hostname: www.all2e.com
Server Port: 80
Document Path: /
Document Length: 12618 bytes
Concurrency Level: 100
Time taken for tests: 0.406355 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 13459225 bytes
HTML transferred: 12972045 bytes
Requests per second: 2460.90 [#/sec] (mean)
Time per request: 40.635 [ms] (mean)
Time per request: 0.406 [ms] (mean, across all concurrent requests)
Transfer rate: 32343.64 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.1 2 3
Processing: 2 37 96.8 5 334
Waiting: 0 34 97.0 3 330
Total: 3 39 96.9 7 337
Percentage of the requests served within a certain time (ms)
50% 7
66% 8
75% 8
80% 8
90% 327
95% 330
98% 333
99% 334
100% 337 (longest request)
As you can see Varnish is now able to handle up to 2500 requests per seconds, which is more than the network interface is able to handle.


