可以使用 Varnish 4 round_robin director 在 404 上重试下一个服务器吗

Can Varnish 4 round_robin director be used to retry next server on 404

我知道有很多关于这个话题的问题和答案。但是大部分都是针对varnish 3或者不使用round_robin director的。

目前我已经使用以下 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);
    }
}

在我的小测试中,这似乎有效。但我不明白这是怎么回事。

bar.backend() 是否记得使用过哪些服务器并跳过那些?或者这只是全局循环,是否有可能,如果在处理过程中有另一个请求进来,服务器会被调用两次?

更新: 以下 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();
}

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);
    }
}

我认为它在你的测试中有效,因为循环法。它会一个接一个地尝试服务器。

我认为在生产设置中这不会工作,因为并发请求。

如果您重试,它将再次通过 vcl_recv 并从导演处获得 backend_hint,无论 req.restarts 值是多少。如果您想要不同的后端,则必须对其进行编码。

一个想法可能是(代码未测试,您将不得不调整 X 后端比较):

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);
    }
}