【问题标题】:Change backend during retry in Varnish 4在 Varnish 4 中重试期间更改后端
【发布时间】:2016-05-29 23:05:06
【问题描述】:

我希望能够在 Varnish 4 中重试时更改后端。我们已经在使用 Varnish 3 的不同(旧)应用程序上进行了这项工作,但我无法弄清楚v4,也找不到太多文档。我们想要的设置是有 2 套导向器 - 一套用于初始请求,尝试与 varnish 位于同一数据中心的本地服务器,因为这样更快,然后只有在失败时,从不同导向器中随机选择其他服务器数据中心。

在 v3 中,这很容易:

sub vcl_recv {
    if (req.restarts == 0) {
        set req.backend = defaultdirector;
    } else {
        set req.backend = backupdirector;
    }
}

#Then in vcl_fetch and/or vcl_error something like:
if (beresp.status >= 500 && req.restarts < some_max) {
    return(restart);
}

但现在在 v4 中,重启应该被替换为重试,整个文档如下:

在 3.0 中,可以在注意到后端响应错误后执行 return(restart),以更改为不同的后端。

这现在称为 return(retry),并跳回到 vcl_backend_fetch。

这只影响后端获取线程,不影响客户端处理。

但我仍然看到一些人的示例代码包含 return(restart) 而不是 return(retry),并且没有一个使用 retry 命令的示例。

我知道 varnish 不应该再次完成 vcl_recv 中的所有工作(例如剥离 cookie),因为只有与后端的通信失败,所以反弹回后端获取确实有意义而不是重做所有前端处理,但是如果我尝试在 vcl_backend_fetch 中更改后端,则会出现编译错误。我该如何完成这项工作?

【问题讨论】:

    标签: varnish varnish-vcl


    【解决方案1】:

    official documentation 有点误导。事实上,restart 仍然存在:您可以在 vcl_deliver 中捕获错误,并在 vcl_recv 中使用 req.backend_hint:

    sub vcl_recv {
        if (req.restarts == 0) {
            set req.backend_hint = defaultdirector.backend();
        } else {
            set req.backend_hint = backupdirector.backend();
        }
    }
    
    sub vcl_deliver {
        if (resp.status >= 500 && req.restarts < some_max) {
            return(restart);
        }
    }
    

    或者,如果更合适,您可以在 vcl_backend_responsevcl_backend_fetch 之间使用 retry

    sub vcl_backend_fetch {
        if (bereq.retries > 0) {
            set bereq.backend = backupdirector.backend();
        }
    }
    
    sub vcl_backend_response {
        if (beresp.status >= 500 && bereq.retries < some_max) {
            return(retry);
        }
    }
    

    【讨论】:

    • 部分正确。事实证明,清漆文档不仅具有误导性,而且完全是错误的。重新启动没有被重试取代。 Restart 仍然存在,并且功能如您所述 - 它只需要在 vcl_deliver 中用于 v4 而不是在 v3 中工作的 vcl_fetch 。至于您关于使用 vcl_backend_fetch 的第二个建议,那根本不起作用(这是我沮丧的根源,因为这是文档建议应该起作用的)。它会生成编译器错误“'req.backend_hint': cannot be set in method 'vcl_backend_fetch'”。
    • 对不起,我在第二个示例中犯了一个错误(在设置后端时使用 req 而不是 bereq),现在已修复。但是,在 bereq 上,您应该使用 bereq.backend 来设置后端。
    • 好的,至少可以编译。我还没有测试它是否正常工作,或者 bereq.retries 计数器是否正确增加(如果后端发生变化则不会重置),但这是一个开始。值得注意的是,为了希望为其他人节省数小时不必要的挫败感,请注意 vcl_recv 中的语法是 req.backend_hint = director_name.backend();,但在 vcl_backend_fetch 中,它是 bereq.backend = director_name.backend();
    • 确实,director 的语法在 v4 中发生了变化。但请注意,根据 director 类型,backend() 方法可能需要一个强制参数。
    • 注意bereq.retries上的测试是没用的:在max_retries之后会自动停止(见varnish-cache.org/docs/4.1/reference/varnishd.html#max-retries
    猜你喜欢
    • 1970-01-01
    • 2017-01-18
    • 2016-06-29
    • 2013-01-30
    • 1970-01-01
    • 2015-03-10
    • 1970-01-01
    • 2020-03-16
    • 2017-01-19
    相关资源
    最近更新 更多