是否存在具有异步更新的HTTP缓存代理?

时间:2017-03-02 05:28:59

标签: http caching proxy varnish

我必须在一个非常慢的API前放置一个缓存服务。 api响应大约40秒,这对我的用户来说太长了。我想使用像Varnish这样的东西来缓存响应。

这是我的问题:

当缓存服务第一次被点击时,从上游API获取响应大约需要40秒。所有连续请求将直接从缓存提供。当缓存TTL已过期时,缓存服务必须再次命中缓慢的API并等待40秒,这是不可接受的。有没有办法通过做某种异步后台缓存更新来避免它?如果是这样,Varnish能做到吗?

为简单起见,我们假设所有客户端请求都是相同的。

如果缓存服务每秒被攻击数百次,情况实际上要糟糕得多。等待刷新缓存的40秒长将排队数千个客户端请求,这可能导致不同类型的问题,包括丢弃连接。我假设Varnish足够智能,它只会触发上游API调用一次并将其他请求排队,直到它得到响应。

Varnish或其他替代方案是否保留最后一次的好副本?如果我的慢速API已经关闭并且根本没有响应,那么即使它已经过期,是否可以从缓存服务LKGC?

实现这一切的最佳软件是什么?

1 个答案:

答案 0 :(得分:1)

Varnish通过宽限模式绝对支持此功能。你需要一点VCL code magic to enable grace mode。这就是它:

  • 初始请求会很慢。它会被一些TTL缓存。
  • 当为初始请求定义宽限期时,Varnish将缓存对象保持在其TTL之外。那段时间被称为“宽限期”。
  • 如果后续请求是针对已过期但仍处于宽限期内的对象,则Varnish将返回陈旧的缓存对象,同时执行异步后端请求

因此,只有初始请求会很慢。客户将获得刷新请求,不会有任何延迟。

基本上,您希望将“健康的后端宽限期”设置为后端生成响应所需的最长时间。例如:

sub vcl_hit {
    if (obj.ttl >= 0s) {
        # normal hit
        return (deliver);
    }
    # We have no fresh fish. Lets look at the stale ones.
    if (std.healthy(req.backend_hint)) {
        # Backend is healthy. Limit age to 45s.
        if (obj.ttl + 45s > 0s) {
            set req.http.grace = "normal(limited)";
            return (deliver);
        } else {
            # No candidate for grace. Fetch a fresh object.
            return(fetch);
        }
    } else {
        # backend is sick - use full grace
        if (obj.ttl + obj.grace > 0s) {
            set req.http.grace = "full";
            return (deliver);
        } else {
            # no graced object.
            return (fetch);
        }
    }
}

在这个例子中,我将它设置为45秒。这样可以确保缓慢的API请求可能需要40秒。