3 Tips to Boost the Performance of your Varnish Cache

High Availability, Scalability and Speed

This story presents three tips to increase the High availability and Scalability of your Varnish cluster, and increase Speed as well:
1. Sharded caching
2. Dynamic backend resolution
3. Browser optimization

TIP #1 : Sharded caching

Create a highly available, self-routing sharded cache cluster is easy with Varnish. Thus, when you add a new node to the cluster, it scales automatically.

Sharding configuration highlight

We define a cluster of Varnish cache (lines 5 to 12).

Next, define a hash director for our cluster (lines 15 to 17).

Finally, we check if the hash director points to this node or to another node (lines 23 to 28).

If the hash director points to another node, we simply pass the request to that node.

Not shown here, but adding a health probe is a plus (an example at the end of the story).

TIP #2 : Dynamic backend resolution

A backend server is defined by a FQDN. At startup, Varnish converts it into an IP and cannot be changed unless a restart.

For a dynamic backend resolution, the best library founded is libvmod-dynamic. You may have to compile it yourself but at least, it works perfectly !

In this example, we build a specific backend for api1.domain.com (lines 19 to 24, and line 27). The name resolution information will be refreshed by background threads after a configurable time to live (line 22).

dynamic backend resolution highlight

TIP #3 : Browser optimization

Browser limits the number of concurrently HTTP requests on the same domain (RFC2616). Of course, you cannot change the client’s browser configuration, but you can work around this limitation.

To override this limit, multiple DNS A entries have to be created:
cache-{s}.domain.com, with s between 1 and 4, to help the browser dealing with numerous requests. This is according to leafletjs.com recommendations.

Let’s override the browser limitation, it can handle it.

For example, an image is about 30ko and could be downloaded in approximately 320ms, which is nearly 3 images per second. Let say we have a standard browser which can handle 6 connections simultaneous.

A = number of images per second in one connection
B = number of connection simultaneous in the browser
C = number of subdomains
D = number of images per second
A x B x C = D

In this example, a standard browser can display 72 images per second, instead of 18.

This limit can be reached when you fetch a lot of images to display a large mosaic, for instance Google Maps tiles.

Varnish configuration

Finally, I share with you a configuration that includes the advices 1 & 2 : Sharding and Dynamic backend resolution.

In this configuration there is :

  • 2 probes : One for checking sharding nodes and the other one to check backend API
  • 2 nodes : Our cluster is made of node01 and node02
  • /health : return “OK” and a HTTP code 200 (line 62, lines 145 to 151)
    /path1 : fetch and cache the first backend API
    /path2 : fetch and cache the second backend API
  • A cleaning of unnecessary headers (lines 134 to 140)
  • Content retention in cache is 30 days (line 113)

Nicolas Béguier