Multiple Backends With Varnish

Varnish has been able to provide caching for more than one backend for quite some time. The achilles heel with this has up until now been that it hasn’t been able to determine whether a backend is healthy or not. This is now a problem of the past! The backend health polling code is available in 2.0 beta1 Sadly it had a bug, so when using the ‘random' director, it was unable to use the remaining healthy backend if all but one went MIA. I reported this bug and it was fixed in changeset r3174.

So as of now, you can safely use one varnish instance for several front-ends, thus eliminate double-caching (memory waste, unnecessary load on back-ends), reduce network traffic, do rudimentary load balancing, ease management etc. With the obscene amount of traffic Varnish can push without putting a fairly basic system under any load worth mentioning, you can use a single front-end to serve several nodes in most setups.

Here’s an elementary sample VCL for how to do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
backend node0 {       
  .host = "127.0.0.1";
  .port = "80";
  .probe = { 
           .url = "/";
           .timeout = 50 ms; 
           .interval = 1s; 
           .window = 10;
           .threshold = 8;

  }
}

backend node1 {
  .host = "10.0.0.2";
  .port = "80";
  .probe = {       
#           .url = "/";
           .timeout = 100 ms;
           .interval = 1s;     
           .window = 10;     
           .threshold = 8;     
        .request =
            "GET /healthcheck.php HTTP/1.1"
            "Host: 10.0.0.2"
            "Connection: close"
            "Accept-Encoding: foo/bar" ;
  }
}
director cl1 random {
    { .backend = node0; .weight = 1; }
    { .backend = node1; .weight = 1; }
}

#director cl1 round-robin {
#   { .backend = node1; }
#   { .backend = node0; }
#}

sub vcl_recv {
        set req.backend = cl1;
}


As you can see I’m defining the backends slightly differently. You need to define one of .url or .request, but not both for obvious reasons. If you go for the slighly simpler .url the default request looks like this:

1
2
3
GET / HTTP/1.1
Host: something
Connection: close


If this does not suit your need, comment out .url and use .request to roll your own. This aspect of Varnish is actually quite well documented, so I won’t repeat what’s on the trac page.

There is clearly a lot more you can and, more often than not, should do in the VCL than the above. This is a stripped down version which only pertains to the backend polling functionality.

Sep 15th, 2008