Using multiple backends in Varnish
The most common Varnish setups will feature a single backend, as illustrated in the VCL snippet below:
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
VCL example
The example below has 2 backends:
default
that connects tobackend.example.com
on port80
image
that connects toimage.example.com
on port80
The image
backend in the example is only used when the URL ends with .png
, .jpg
or .svg
.
By conditionally assigning a value to the req.backend_hint
variable in VCL, a backend is selected for that specific condition.
In the example below, every cache miss will be sent to the default
backend, except the cache misses for the images:
vcl 4.1;
backend default {
.host = "backend.example.com";
.port = "80";
}
backend image {
.host = "image.example.com";
.port = "80";
}
sub vcl_recv {
if(req.url ~ "\.(png|jpg|svg)$") {
set req.backend_hint = image;
}
}
Beware of unused backends
If you’re using multiple backends, make sure all the defined backends are in use. When a backend is not in use, Varnish will return the following error when it compiles the VCL file:
Error:
Message from VCC-compiler:
Unused backend image, defined:
('/etc/varnish/default.vcl' Line 7 Pos 9)
backend image {
--------######--
Running VCC-compiler failed, exited with 2
VCL compilation failed
Varnish complains that the image
backend was defined but not used, as you can see in the VCL example below:
vcl 4.1;
backend default {
.host = "backend.example.com";
.port = "80";
}
backend image {
.host = "image.example.com";
.port = "80";
}
default
backend will automatically be used because it was defined first. But without additional backend allocation logic Varnish’s VCC compiler will throw an error.The solution is to either remove the image
backend or to assign the backend in our VCL code as we have done in the initial VCL example.
Loadbalancing requests between multiple backends
In the VCL example we assigned backends based on routing decisions: certain content had to be served from a specific backend.
Although the use of multiple backends will offload some of the server load from the primary backend, the distribution is far from predictable.
For actual loadbalancing between multiple backends you should leverage vmod_directors
. Here’s an example of round-robin based load distribution across 3 backends:
vcl 4.1;
import directors;
backend backend1 {
.host = "backend1.example.com";
.port = "80";
}
backend backend2 {
.host = "backend2.example.com";
.port = "80";
}
backend backend3 {
.host = "backend3.example.com";
.port = "80";
}
sub vcl_init {
new vdir = directors.round_robin();
vdir.add_backend(backend1);
vdir.add_backend(backend2);
vdir.add_backend(backend3);
}
sub vcl_recv {
set req.backend_hint = vdir.backend();
}
But for more in-depth information about loadbalancing in Varnish, please read the dedicated loadbalancing tutorial.