caching - Varnish - stale-while-revalidate 似乎没有重新验证

标签 caching varnish cache-control

我们正在使用Varnish缓存6.2来位于WebAPI后端的前面。
后端会在某些请求上向后发送一个缓存控制 header ,以便我们可以缓存更长的时间。

但是-如果后端出现故障并保持故障状态,我们将在一个小时内重新发送过期的验证信息。

因此,后端的典型缓存控制响应 header 如下所示:

public, max-age=30, stale-while-revalidate=3600

在我们的Varnish VCL中,我们添加了一个例程,该例程可在某些错误时停止后台获取。这是为了阻止来自后端的错误响应进入缓存:
sub vcl_backend_response {
    if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504)
    {
        if (bereq.is_bgfetch)
        {
            return (abandon);
        }

        set beresp.ttl = 1s;
    }
}

我们面临的问题很简单-Max-Age过期后,即使后端可用,Varnish也不更新缓存中的项目。 (并且响应发生了变化)
我们已经看到来自Varnish的响应“Age” header 超过200s且响应错误的问题。我们还看到了“Age” header 为1-3s的情况,这表明发生了后台获取(或正常获取)。

这种情况经常发生,足以引起我们的注意-但并非在每个请求中都如此。

我尝试了一个简单的“通过”,例如Varnish中的以下内容:
sub vcl_recv {
    return(pass);
}

但是,这似乎没有效果。

使用Varnish设置是否还有其他可能导致上述情况的情况?

编辑,根据评论,这是我们添加到与请求进行交互的每个子项中的一件小事,以查看实际发生的情况:
sub vcl_deliver {
    if (obj.uncacheable) {
        set req.http.x-cache = req.http.x-cache + " uncacheable" ;
    } else {
        set req.http.x-cache = req.http.x-cache + " cached" ;
    }

    set resp.http.x-cache = req.http.x-cache;
}

sub vcl_hit {
    set req.http.x-cache = "hit";
}

最佳答案

这是预期的行为。如果对象是第一次从后端获取的(即t=0),则Varnish会对其进行缓存,将beresp.ttl设置为30s,将beresp.grace设置为3600s。然后,如果您在t=3000时将对象请求为Varnish,则旧对象将被传递到客户端(即Age: 3000),并且将触发异步后台获取以刷新缓存的对象。如果您在t=3001时再次向Varnish请求对象,如果后台获取已完成其工作,则将交付一个新对象(即Age: 1)。以下测试说明了此行为:

varnishtest "..."

server s1 {
    rxreq
    txresp -hdr "Cache-Control: public, max-age=1, stale-while-revalidate=60" \
           -hdr "Version: 1"

    rxreq
    txresp -hdr "Cache-Control: public, max-age=1, stale-while-revalidate=60" \
           -hdr "Version: 2"
} -start

varnish v1 -vcl+backend {
} -start

client c1 {
    txreq
    rxresp
    expect resp.http.Version == 1
    expect resp.http.Age == 0

    delay 5.0

    txreq
    rxresp
    expect resp.http.Version == 1
    expect resp.http.Age == 5

    delay 0.1

    txreq
    rxresp
    expect resp.http.Version == 2
    expect resp.http.Age == 0
} -run

varnish v1 -expect client_req == 3

为了在缓存中的项目消耗其TTL之后同步刷新对象,您需要在req.grace期间使用vcl_recv进行播放。如果后端正常,则可能需要将其设置为0s。请检查https://varnish-cache.org/docs/trunk/users-guide/vcl-grace.html#misbehaving-servers了解详细信息。

关于caching - Varnish - stale-while-revalidate 似乎没有重新验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58396657/

相关文章:

objective-c - iOS缓存库不起作用

apache - 如何设置 Varnish 以与 Apache 和 Tomcat 一起工作

javascript - 我应该在我的 HTML 中放入什么来确保用户获得我页面的最新版本,而不是旧版本?

android - 我可以在缓存之前以某种方式从 OkHttp 响应中删除 header 吗?

http - 对于可以更改的内容,哪些是与缓存相关的最佳 HTTP header ?

caching - 如何使用 Varnish 缓存发布请求?

django - 注销不起作用,在 nginx 上缓存,如何允许注销?

wordpress - 我的 WordPress 网站中的 "Endurance Cache"功能是什么?

wordpress - 新帖子发布后,我需要清除APC缓存吗?

php - nGinx 和 PhpMyAdmin 重定向问题上的 Varnish