I know there are a lot of questions and answers on this topic. But most of them are for Varnish 3 or don't use the round_robin director.
Currently i've tested with the following VCL:
sub vcl_init {
new bar = directors.round_robin();
bar.add_backend(cbweb1);
bar.add_backend(cbweb2);
}
sub vcl_recv {
set req.backend_hint = bar.backend();
unset req.http.Cookie;
}
sub vcl_deliver {
if(resp.status == 404 && req.restarts < 1)
{
return(restart);
}
}
In my small test, this appears to work. But I don't understand how this works.
Does the bar.backend() remembers which servers have been used and skips those? Or is this just round-robinning globally, is it possible, a server would be called twice if another requests comes in during processing?
Update: The following VCL appears to work:
sub vcl_init {
new bar = directors.round_robin();
bar.add_backend(cbweb1);
bar.add_backend(cbweb2);
}
sub vcl_recv {
set req.backend_hint = bar.backend();
}
sub vcl_backend_fetch
{
if (bereq.retries > 0)
{
if(bereq.http.X-Backend == "cbweb1")
{
set bereq.backend = cbweb2;
}
else
{
set bereq.backend = cbweb1;
}
}
}
sub vcl_backend_response {
set bereq.http.X-Backend = beresp.backend.name;
if (beresp.status == 404 && bereq.retries < 1) {
return(retry);
}
}
I think it works in your test because of round robin. It will try servers one after each other.
I think in a production setup this won't work because of concurrent requests.
If you retry, it will go again through the vcl_recv and get a backend_hint from the director, whatever is the req.restarts value. If you want a different backend then you will have to code it.
An idea could be (code not tested, you will have to adapt the X-backend comparison):
sub vcl_init {
new bar = directors.round_robin();
bar.add_backend(cbweb1);
bar.add_backend(cbweb2);
}
sub vcl_recv {
if (req.restarts > 0){
if (req.X-backend == cbweb1 ){
set req.backend_hint = cbweb2;
}
if (req.X-backend == cbweb2 ){
set req.backend_hint = cbweb1;
}
}
else {
set req.backend_hint = bar.backend();
}
set req.X-backend = req.backend_hint
unset req.http.Cookie;
}
sub vcl_deliver {
if(resp.status == 404 && req.restarts < 1)
{
return(restart);
}
}