为什么有这么多的清漆?

时间:2016-07-28 16:46:32

标签: caching varnish varnish-vcl varnish-4

我有一个带有后端的清漆缓存(版本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);
            }

}

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

但是,我发现现在我有更多的"传递"请求。请求当然,清漆应该缓存(在它之前)。 Aprox * 100以上。所以我解决了一个问题,但是我创造了另一个问题。

未设置cookie(在recv和后端响应中),强制清除缓存。

unset beresp.http.set-cookie;

unset req.http.Cookie;

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

1 个答案:

答案 0 :(得分:0)

  

但只有这种配置,如果后端生病了   对象不存在于缓存中,varnish返回503(我想要   从后端获取)。为了避免这种行为,我必须使用相同的conf   在vcl_miss中强制清除从"生病的"后端:

     

...

我认为这种假设是错误的。 vcl_miss子例程等同于内置子例程;你总是在执行return (fetch)。当宽限内容不可用时,添加该代码不会强制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