0

I've set up one server with Varnish as a load balancer and two servers running nginx/unicorn/sinatra for demo purpose. All three servers are accessible! My varnish vcl file:

backend web2 {
  .host = "10.169.42.243";
  .port = "80";
  .probe = {
    .url = "/";
    .interval = 5s;
    .timeout = 1 s;
    .window = 5;
    .threshold = 3;
  }
}

backend web1 {
    .host = "10.47.137.196";
    .port = "80";
    .probe = {
      .url = "/";
      .interval = 5s;
      .timeout = 1 s;
      .window = 5;
      .threshold = 3;
    }
  }

director demo round-robin {
    { .backend = web1; }
    { .backend = web2; }
}

sub vcl_recv {
    set req.backend = demo; 
}

Health check are also good for both backends:

0 Backend_health - web1 Still healthy 4--X-RH 5 3 5 0.004336 0.003621 HTTP/1.1 200 OK
0 Backend_health - web2 Still healthy 4--X-RH 5 3 5 0.003388 0.004753 HTTP/1.1 200 OK

My Sinatra app just show the ip of the host: require "rubygems" require "sinatra/base" require "socket"

class MyApp < Sinatra::Base

  get '/' do
    headers \
      "Cache-Control"   => "no-cache, no-store, must-revalidate",
      "Pragma"   => "no-cache",
      "Expires"   => "0"
    'Hello, nginx and unicorn! - ' + Socket.gethostname
  end

end

But when I access the address of the load balancer I' always shown the same IP address. I can visit both backends manually and see their unique IPs.

Did I miss something obvious?

Edit: I also tried curl from the Varnish machine and can see the correct response from the backends. When shutting down one of the web servers Varnish will use the other one. But shouldn't this happen on each request?

Edit2: Ok I did more investigation via the nginx access_log files and I could see that Varnish does not do a new lookup for every request. With the given headers I thought Varnish would not cache the content. What's the error here?

soupdiver
  • 807
  • 2
  • 9
  • 26

1 Answers1

0

You didn't mention which version of Varnish you are using. If memory serves me right, Varnish hasn't always respected Cache-Control header. The current builtin.vcl does check for the header though.

Try adding the following to your default.vcl and see if it makes a difference:

sub vcl_fetch {

  # Varnish determined the object was not cacheable
  if (!(beresp.ttl > 0s)) {
    set beresp.http.X-Cacheable = "NO:Not Cacheable";
    return(hit_for_pass);
  }
  elseif (req.http.Cookie) {
    set beresp.http.X-Cacheable = "NO:Got cookie";
    return(hit_for_pass);
  }
  elseif (beresp.http.Cache-Control ~ "private") {
    set beresp.http.X-Cacheable = "NO:Cache-Control=private";
    return(hit_for_pass);
  }
  elseif (beresp.http.Cache-Control ~ "no-cache" || beresp.http.Pragma ~ "no-cache") {
    set beresp.http.X-Cacheable = "Refetch forced by user";
    return(hit_for_pass);
  # You are extending the lifetime of the object artificially
  }
  elseif (beresp.ttl < 1s) {
    set beresp.ttl   = 5s;
    set beresp.grace = 5s;
    set beresp.http.X-Cacheable = "YES:FORCED";
  # Varnish determined the object was cacheable
  } else {
    set beresp.http.X-Cacheable = "YES";
  }
}

The VCL above is for Varnish 3.0, and it checks for various conditions that should prevent content from being cached, returns a hit_for_pass for the non-cacheable items, and sets X-Cacheable header accordingly.

Ketola
  • 311
  • 1
  • 3