0

我有一个清漆缓存(版本 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 和后端响应中),以强制清漆进行缓存。

unset beresp.http.set-cookie;

unset req.http.Cookie;

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

4

1 回答 1

0

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

...

我认为这个假设是错误的。该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
于 2016-07-30T09:09:14.063 回答