3

我对在 varnish 4 中设置宽限时间的位置感到困惑。我已经看到示例 VCL 在vcl_recv中设置宽限时间

sub vcl_recv {
    ...
    set req.http.grace = 60m;
    ...
}

其他人将其设置在vcl_hit

sub vcl_hit {
    ...
    set obj.grace = 60m;
    ...
}

并在他们在vcl_backend_response中设置的文档(https://www.varnish-cache.org/docs/4.0/users-guide/vcl-grace.html)中

sub vcl_backend_response {
    ...
    set beresp.grace = 60m;
    ...
}

我还看到了在vcl_recvvcl_backend_response中设置宽限时间的示例。

谁能解释一下为什么要把它放在一个特定的地方?

在实践中,我想根据后端是否被认为是健康的来设置宽限时间;直观地说,我会在 varnish 联系后端之前设置它,所以我会在vcl_recv中设置宽限时间,并决定是否从vcl_hit中的缓存服务器,如下所示:

sub vcl_recv {
    ...
    if (std.healthy(req.backend_hint)) {
        set req.http.grace = 2m;
    } else {
        set req.http.grace = 60m;
    }
    ...
}

sub vcl_hit {
    if (obj.ttl >= 0s) {
        # A standard hit, deliver from cache
        return (deliver);
    }
    elsif (obj.ttl + obj.grace > 0s) {
        # page expired, serve from cache in the meantime
        return (deliver);
    } else {
        return (fetch);
    }
}

这是正确的方法吗?

4

1 回答 1

4

这是我迄今为止的研究结果:

  1. vcl_recv中设置req.http.grace没有帮助,因为这只是定义了一个新的标头条目,否则 varnish 将忽略它
  2. vcl_hit中设置obj.grace不起作用,因为 obj 在 varnish 4 中是只读的
  3. 可以设置宽限时间以便 varnish 识别它的唯一位置是在 beresp.grace 的子例程vcl_backend_response
  4. 因为宽限时间只能在vcl_backend_response中设置,因此无法根据后端运行状况设置不同的宽限时间,因为仅当 varnish 在缓存未命中后从后端获取数据时才调用此函数,这对于我想要的来说太晚了。我需要在联系后端之前设置宽限时间。

我根据后端运行状况设置不同宽限时间的解决方案是:

  1. 我将宽限时间设置为 2 个宽限时间的最大值:“正常宽限时间”和“后端生病时的宽限时间”
  2. 是从缓存服务还是联系后端由vcl_hit决定;那是我可以模拟第二次宽限期的地方

这是我的vcl_hit的样子

sub vcl_hit {
        if (obj.ttl >= 0s) {
                # A standard hit, deliver from cache
                return (deliver);
        }
        elsif (std.healthy(req.backend_hint)) {
                if (obj.ttl + 30m > 0s) {
                        # page expired within a limited grace time and backend
                        # is healthy: deliver from cache while cache is updated
                        # asynchronous
                        return (deliver);
                } else {
                        # page expired too long ago - fetch from backend
                        return (fetch);
                }
        }
        else {
                if (obj.ttl + obj.grace > 0s) {
                        # backend is not healthy - provide the page from cache
                        # during full grace time set in vcl_backend_response
                        return (deliver);
                } else {
                        # page expired for the full grace time and backend is
                        # considered unhealthy - try to contact the backend
                        # anyway
                        return (fetch);
                }
        }
}

在这里,我使用条件“定义”了 30 分钟的第二次宽限时间

            if (obj.ttl + 30m > 0s) {

vcl_backend_response 中,我只设置了 6 小时的最大宽限时间:

sub vcl_backend_response {
        # define full grace time here
        set beresp.grace = 6h;
        ...
}
于 2015-10-07T16:59:22.797 回答