Varnish的问题

时间:2017-10-03 09:30:08

标签: reactjs react-redux varnish varnish-vcl varnish-4

我们正在开发一个使用React和Redux的网站。我们刚刚在我们的API上添加了一个Varnish缓存,虽然在Postman上测试API时一切似乎都运行良好,但这在我们的网站上运行不正常。

出于某种原因,所有API查询在第一次完成时都会失败并显示401状态代码,但是,它们在第一次失败后工作正常。

一旦我们添加了Varnish缓存,这种行为就开始发生了,但是,我们无法找到错误。

Varnish配置文件如下:

vcl 4.0;

backend default {
    .host = ...;
    .port = ...;
}

sub vcl_backend_response {
    set beresp.ttl = 5m;

    # Don't cache non-200 responses
    if ( beresp.status != 200 ) {
        set beresp.ttl = 0s;
    }
    # Don't cache if "no-cache" or "private" on cache control
    if (beresp.http.cache-control ~ "(no-cache|private)" ||
        beresp.http.pragma ~ "no-cache") {
            set beresp.ttl = 0s;
    }

}

sub vcl_recv {
    # Do not cache Healthcheck call
    if (req.url == "/api/healthcheck") {
        return (pass);
    }

    # Do not cache POST methods
    if (req.method == "POST") {
        return (pass);
    }

    # Do not cache users' calls as each user will be different
    if (req.url ~ "\/api\/v[a-zA-Z0-9\.]+\/users\/.*") {
        return (pass);
    } 

    # Ensure that cache is enabled to any call to the API
    if (req.url ~ "/api/*") {
        return (hash);
    }   
}

sub vcl_deliver {
  if (req.url ~ "/api/*") {
    set resp.http.Access-Control-Allow-Headers = "Accept, Accept-Encoding, Authorization, Content-Type, Dnt, Origin, User-Agent, X-CSRFToken, X-Requested-With";
    return (deliver);
  } 
}

可能会发生什么?

非常感谢

2 个答案:

答案 0 :(得分:1)

我终于找到了我的问题,我的配置文件中缺少一个返回(哈希)。

正确的配置文件如下:

vcl 4.0;

backend default {
    .host = ...;
    .port = ...;
}

sub vcl_backend_response {
    set beresp.ttl = 5m;

    # Don't cache non-200 responses
    if ( beresp.status != 200 ) {
        set beresp.ttl = 0s;
    }
    # Don't cache if "no-cache" or "private" on cache control
    if (beresp.http.cache-control ~ "(no-cache|private)" ||
        beresp.http.pragma ~ "no-cache") {
            set beresp.ttl = 0s;
    }

}

sub vcl_recv {
    # Do not cache Healthcheck call
    if (req.url == "/api/healthcheck") {
        return (pass);
    }

    if (req.method != "GET" && req.method != "HEAD") {
        # We only deal with GET and HEAD by default
        return (pass);
    }

    # Do not cache users' calls as each user will be different
    if (req.url ~ "\/api\/v[a-zA-Z0-9\.]+\/users\/.*") {
        return (pass);
    }
    return (hash);
}

sub vcl_deliver {
  if (req.url ~ "/api/*") {
    set resp.http.Access-Control-Allow-Headers = "Accept, Accept-Encoding, Authorization, Content-Type, Dnt, Origin, User-Agent, X-CSRFToken, X-Requested-With";
    return (deliver);
  }
}

答案 1 :(得分:0)

我想我还会发布将Varnish应用于需要某种授权的API请求的人(即使你说你解决了你的问题)。

如果您碰巧需要对 {/ 1>}范围之外的路径进行授权,那么401可能仍会发生,因为这些请求可能仍会被缓存。

此外,您也可以(并且出于性能原因)缓存经过身份验证的请求。对此和401错误的简单解决方案是通过令牌标头的值来改变您的缓存。

解决方案1。

您可以更改应用程序代码,只需发送额外的HTTP标头:dbMetadataWriter.writeMetadata(successReports);。这足以指示Varnish缓存在API的不同用户之间应该有所不同。

解决方案2.

如果你无法调整你的应用程序,那么一些VCL可以提供帮助:

\/api\/v[a-zA-Z0-9\.]+\/users\/.*

P.S。通常不建议将"尾随" Vary: X-Token中的sub vcl_backend_response { if (!beresp.http.Vary) { # no Vary at all set beresp.http.Vary = "X-Token"; } elsif (beresp.http.Vary !~ "X-Token") { # add to existing Vary set beresp.http.Vary = beresp.http.Vary + ", X-Token"; } ... } 以确保builtin vcl_recv例程仍然可以运行。