Varnish installation and setup on ez publish based systems

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:

http://www.all2e.com

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:

http://nocache.all2e.com

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.

http://www.all2e.com/Ressourcen/Artikel-und-Fallstudien/Varnish-installation-and-setup-on-ez-publish-based-systems

Kommentare

RE: ( Andrey)

Could you explain please. Do I need ezvlogin extension for ezpublish 4.1 where the seting of is_logged_in coockie already works?

RE: ( Vegard)

Hello, great guide! On Linux you need to run "ldconfig" after make install in order to update the libs. If not varnish will not find the libvarnish.so.1-file.