取决于后端健康状况的清漆 4 宽限时间

varnish 4 grace time depending on backend health

我对在 varnish 4 中设置宽限时间的位置感到困惑。我在 vcl_recv[=15= 中看到了 VCL 设置宽限时间的示例]

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

其他设置在vcl_hit

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

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

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

我也看到过在 vcl_recvvcl_backend_response 中设置宽限时间的示例.

谁能解释一下为什么要将它设置在一个特定的地方?

实际上我想根据后端是否健康来设置宽限时间;直觉上我会在 before 清漆联系后端,所以我会在 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);
    }
}

这是正确的方法吗?

这是我目前的研究结果:

  1. vcl_recv 中设置 req.http.grace 没有帮助,因为这只是定义了一个新的 header条目,否则清漆将忽略它
  2. vcl_hit 中设置 obj.grace 不起作用,因为对象在清漆 4 中是只读的
  3. 唯一可以设置宽限时间以便 varnish 识别它的地方是 vcl_backend_response 中的子例程 beresp.grace
  4. 因为宽限时间只能在vcl_backend_response中设置,根据后端健康设置不同的宽限时间是不可能的,因为这个函数只在清漆时调用在缓存未命中后从后端获取数据,这对我想要的来说已经太晚了。我需要在联系后端之前设置宽限时间。

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

  1. 我将宽限时间设置为 2 个宽限时间中的最大值:"normal grace time" 和 "grace time when backend is sick"
  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);
                }
        }
}

我在这里 "defined" 使用条件

的第二次宽限时间为 30 分钟
            if (obj.ttl + 30m > 0s) {

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

sub vcl_backend_response {
        # define full grace time here
        set beresp.grace = 6h;
        ...
}