【问题标题】:why have so many pass in varnish?为什么有这么多通过清漆?
【发布时间】:2016-12-03 04:42:33
【问题描述】:

我有一个清漆缓存(版本 4),其后端有时会变得“慢”。当这个后端“慢”到不饱和时,我使用健康检查来强制清漆从缓存中提供陈旧的内容。

所以定义了mi后端:

backend api {
    .host = "111.111.111.111";
    .port = "80";
    .first_byte_timeout = 300s;
    .probe = {
            .url = "/some/url";
            .expected_response = 200;
            .timeout = 80ms;
            .interval = 120s;
            .window = 1;
            .threshold = 1;
    }

}

backend apibackup {
    .host = "111.111.111.111";
    .port = "80";
    .first_byte_timeout = 300s;
    .probe = {
            .url = "/some/url";
            .expected_response = 200;
            .timeout = 80ms;
            .interval = 120s;
            .window = 1;
            .threshold = 1;
    }

}

并配置宽限模式:

sub vcl_hit {
    if (obj.ttl > 0s) {
            # A standard hit, deliver from cache
            return (deliver);
    }
    elsif (std.healthy(req.backend_hint)) {
            if (obj.ttl + 30s > 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);
            }
    }

}

但只有在这种配置下,如果后端有问题并且缓存中不存在对象,varnish 会返回 503(我想从后端获取)。为了避免这种行为,我必须在 vcl_miss 中放置相同的 conf 以强制清漆从“病态”后端获取内容:

sub vcl_miss{

    if (std.healthy(req.backend_hint)) {
                    return (fetch);
            }
    else {
                    set req.backend_hint = apibackup;
                    return (fetch);
            }

}

这样,结果正如预期的那样,当后端很慢时,清漆从缓存中提供陈旧的内容并且响应时间得到改善。

但是,我发现现在我有更多的“通过”请求。请求当然,清漆应该缓存(并且在它之前)。大约 * 100 多个。所以我解决了一个问题,但我又创建了另一个问题。

cookie 未设置(在 recv 和后端响应中),以强制 varnish 进行缓存。

unset beresp.http.set-cookie;

unset req.http.Cookie;

所以,我的问题是……为什么我有很多通行证请求?我怎么能避免呢?

【问题讨论】:

    标签: caching varnish varnish-vcl varnish-4


    【解决方案1】:

    但只有在这种配置下,如果后端有问题并且 缓存中不存在对象,清漆返回 503(我想 从后端获取)。为了避免这种行为,我必须把相同的 conf 在 vcl_miss 中强制清漆从“病态”后端获取内容:

    ...

    我认为这个假设是错误的。那个vcl_miss 子程序相当于内置的子程序;你总是在执行return (fetch)。当宽限内容不可用时,添加该代码不会强制 Varnish 使用有问题的后端。事实上,据我所知,你根本不能强迫 Varnish 使用有病的后端。

    我创建了一个玩具 Varnish 测试用例来证明使用该代码没有任何改变。当宽限内容不可用时,Varnish 永远不会使用有病的后端,因此它会向客户端发送 503 响应。

    varnishtest ""
    
    server s1 {
        rxreq
        expect req.url == "/1"
        txresp -body "foo"
    } -start
    
    varnish v1 -vcl+backend {
        import std;
    
        sub vcl_hit {
            if (obj.ttl > 0s) {
                return (deliver);
            }
            elsif (std.healthy(req.backend_hint)) {
                return (deliver);
            }
            else {
                if (obj.ttl + obj.grace > 0s) {
                    return (deliver);
                } else {
                    return (fetch);
                }
            }
        }
    
        # XXX: nonsense subroutine equivalent to the build-in one just to show this
        # doesn't force Varnish to fetch contents from sick backends.
        sub vcl_miss{
            if (std.healthy(req.backend_hint)) {
                return (fetch);
            } else {
                return (fetch);
            }
        }
    
        sub vcl_backend_response {
            set beresp.ttl = 1s;
            set beresp.grace = 1s;
        }
    } -start
    
    client c1 {
        txreq -url "/1"
        rxresp
        expect resp.status == 200
        expect resp.bodylen == 3
    } -run
    
    varnish v1 -cliok "backend.set_health s1 sick"
    
    delay 1.5
    
    client c1 {
        txreq -url "/1"
        rxresp
        expect resp.status == 200
        expect resp.bodylen == 3
    } -run
    
    delay 1.0
    
    client c1 {
        txreq -url "/1"
        rxresp
        expect resp.status == 503
    
        txreq -url "/2"
        rxresp
        expect resp.status == 503
    } -run
    

    更新的测试用例:

    varnishtest ""
    
    server s1 {
        rxreq
        expect req.url == "/1"
        txresp -body "foo"
    
        rxreq
        expect req.url == "/1"
        txresp -body "foobar"
    
        rxreq
        expect req.url == "/2"
        txresp -body "hello"
    } -start
    
    varnish v1 -vcl {
        import std;
    
        backend default {
            .host = "${s1_addr}";
            .port = "${s1_port}";
        }
    
        backend backup {
            .host = "${s1_addr}";
            .port = "${s1_port}";
        }
    
        sub vcl_hit {
            if (obj.ttl > 0s) {
                return (deliver);
            }
            elsif (std.healthy(req.backend_hint)) {
                return (deliver);
            }
            else {
                if (obj.ttl + obj.grace > 0s) {
                    return (deliver);
                } else {
                    return (fetch);
                }
            }
        }
    
        sub vcl_miss{
            if (!std.healthy(req.backend_hint)) {
                set req.backend_hint = backup;
            }
            return (fetch);
        }
    
        sub vcl_backend_response {
            set beresp.ttl = 1s;
            set beresp.grace = 1s;
        }
    } -start
    
    client c1 {
        txreq -url "/1"
        rxresp
        expect resp.status == 200
        expect resp.bodylen == 3
    } -run
    
    varnish v1 -cliok "backend.set_health default sick"
    
    delay 1.5
    
    client c1 {
        txreq -url "/1"
        rxresp
        expect resp.status == 200
        expect resp.bodylen == 3
    } -run
    
    delay 1.0
    
    client c1 {
        txreq -url "/1"
        rxresp
        expect resp.status == 200
        expect resp.bodylen == 6
    
        txreq -url "/1"
        rxresp
        expect resp.status == 200
        expect resp.bodylen == 6
    
        txreq -url "/2"
        rxresp
        expect resp.status == 200
        expect resp.bodylen == 5
    } -run
    
    varnish v1 -expect cache_hit == 2
    varnish v1 -expect cache_hitpass == 0
    

    【讨论】:

    • 对不起,你是对的。我忘记了一个大细节。我有一个替代后端(但相同)来强制清漆获取内容。
    • 谢谢!这个细节非常重要:) 我已经调整了测试用例以反映您的设置,它按预期工作。我的意思是,内容是从备份后端获取的,cache_hitpass 计数器没有增加。您如何衡量这些“通过”请求?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-17
    • 2012-07-10
    • 1970-01-01
    • 2013-01-31
    • 2016-05-28
    • 1970-01-01
    • 2016-06-14
    相关资源
    最近更新 更多