2

We have a set of 6 backends that serve our website. Because we use multiple datacenters we have found the best performance occurs for us when we have varnish send the request to the localhost httpd server (running on port 81). This of course is a very basic configuration well supported by varnish and can be accomplished using the fallback director:

director default fallback {
    { .backend = localbackend; }
    { .backend = web1; }
    { .backend = web2; }
    { .backend = web3; }
etc...
}

However the fallback director tries the other backends in order till it finds a healthy one. The BIG problem is that in the above config web1 will take all the traffic if localbackend fails !!! This will overload web1 and it will become sick. Then all requests go to web3... and now it will get 3x the normal traffic... cause a cascading failure.

Thus we need instead a config that will allow all requests to sent to the localhost httpd server if it is health, but if not, send the requests to the other healthy servers in a round robin type fashion.

Thank you in advance for any suggestions and solutions you might think of... Your help is GREATLY appreciated.

Warren P
  • 65,725
  • 40
  • 181
  • 316
user1254723
  • 181
  • 1
  • 8
  • 1
    One way i could think of solving this problem, is to set huge weight to your first backend and round-robin director. When first server fails, others will be randomly selected to serve traffic. But you'll still have 1%+ chance to server content from another cache. I'm not sure if it's possible to change backend director when you are in vcl_fetch but you could test this approach to change backend when first backend is not healthy. Or you could try "restart" approachhttps://www.varnish-cache.org/trac/wiki/VCLExampleRestarts – Łukasz Rysiak Apr 16 '12 at 23:14
  • vcl tag is for Delphi users, please tag questions as varnish-vcl – Warren P Jan 21 '13 at 15:37

3 Answers3

2

It can be accomplished in several ways, one of the simplest is:

  1. Set localhost as default backend
  2. Create a round robind director for the rest of backends
  3. Check on top of your vcl_recv if default backend is healthy and if it isn't switch to round robind director.

With this approach you can even switch backends if current request has failed.

Something like:

probe my_probe {
  .url       = "/";
  .interval  = 1s;
  .timeout   = 0.2 s;
  .window    = 3;
  .threshold = 2;
  .initial   = 1;
}
backend default {
  .host  = 127.0.0.1;
  .probe = my_probe;
}
backend server1 {
  .host  = 192.168.8.21;
  .probe = my_probe;
}
backend server2 {
  .host  = 192.168.8.22;
  .probe = my_probe;
}
backend server3 {
  .host  = 192.168.8.23;
  .probe = my_probe;
}
director server_pool round-robin {
  { .backend = server1; }
  { .backend = server2; }
  { .backend = server3; }
}

sub vcl_recv {
  if ( req.backend == default
    && ! req.backend.healthy
  ) {
    set req.backend = server_pool;
  }
  /* Uncomment if you want to divert restarted requests to the server pool
   * if (req.restarts > 0) {
   *   set req.backend = server_pool;
   * }
   */
}
NITEMAN
  • 1,236
  • 10
  • 11
1

This is completely untested, but should theoretically work.

probe healthcheck {
  .url = "/status.php";
  .interval = 60s;
  .timeout = 0.3 s;
  .window = 8;
  .threshold = 3;
  .initial = 3;
  .expected_response = 200;
}

backend server1 {
  .host = "server1.example.com";
  .probe = healthcheck;
}
backend server2 {
  .host = "server2.example.com";
  .probe = healthcheck;
}
backend server3 {
  .host = "server3.example.com";
  .probe = healthcheck;
}

director fallback round-robin {
  { .backend = server1; }
  { .backend = server2; }
  { .backend = server3; }
}

sub vcl_recv {
  # Set backend to fallback director until we find the proper localhost backend.
  # If we can't figure out which is localhost, at least we still work.
  set req.backend = fallback;

  # Set the default backend to localhost by hostname
  if (server.hostname == "server1") {
    set req.backend = server1;
    set obj.http.X-LocalCache = "YES";
  }
  else if (server.hostname == "server2") {
    set req.backend = server2;
    set obj.http.X-LocalCache = "YES";
  }
  else if (server.hostname == "server3") {
    set req.backend = server3;
    set obj.http.X-LocalCache = "YES";
  }

  # If the localhost fails, go to fallback director.
  if (obj.http.X-LocalCache ~ "YES") {
    if (!req.backend.healthy) {
      set req.backend = fallback;
      unset obj.http.X-LocalCache
    }
  }
}

It will automatically figure out which backend is localhost by using the hostname. You just have to make sure the backend names match your hostnames.

0

You can do some basic load balancing with Varnish. Check this out:

https://www.varnish-cache.org/trac/wiki/LoadBalancing

wrdevos
  • 2,029
  • 16
  • 19