可以使用 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的。
- 我在 Varnish 中配置了 2 个网络服务器。
- 一些静态文件可能只在两个网络服务器之一生成。
- 对于 404 响应,我希望 Varnish 尝试其他网络服务器。
目前我已经使用以下 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);
}
}
我知道有很多关于这个话题的问题和答案。但是大部分都是针对varnish 3或者不使用round_robin director的。
- 我在 Varnish 中配置了 2 个网络服务器。
- 一些静态文件可能只在两个网络服务器之一生成。
- 对于 404 响应,我希望 Varnish 尝试其他网络服务器。
目前我已经使用以下 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);
}
}