清漆问题
Issue with Varnish
我们正在使用 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);
}
}
可能发生了什么?
非常感谢
我终于找到了我的问题,我的配置文件中缺少 return(hash)。
正确的配置文件如下:
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);
}
}
我想我仍然 post 对于将 Varnish 应用于 API 需要某种授权的请求的人(即使你说你解决了你的问题)。
如果您碰巧需要对路径 外部 \/api\/v[a-zA-Z0-9\.]+\/users\/.*
范围的授权,那么 401 可能仍会发生,因为这些请求可能仍被缓存。
此外,您还可以(并且应该出于性能原因)缓存经过身份验证的请求。解决该问题和 401 错误的简单方法是根据令牌 header 的值改变缓存。
解决方案 1.
您可以更改您的应用程序代码以简单地发送额外的 HTTP header:Vary: X-Token
。这足以指示 Varnish API.
的不同用户之间的缓存应该不同
解决方案 2.
如果你没有办法调整你的应用程序,那么一些VCL可以提供帮助:
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";
}
...
}
P.S。通常不建议将 "trailing" return
放在 vcl_recv
中,以确保 builtin vcl_recv 例程仍然 运行。
我们正在使用 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);
}
}
可能发生了什么?
非常感谢
我终于找到了我的问题,我的配置文件中缺少 return(hash)。
正确的配置文件如下:
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);
}
}
我想我仍然 post 对于将 Varnish 应用于 API 需要某种授权的请求的人(即使你说你解决了你的问题)。
如果您碰巧需要对路径 外部 \/api\/v[a-zA-Z0-9\.]+\/users\/.*
范围的授权,那么 401 可能仍会发生,因为这些请求可能仍被缓存。
此外,您还可以(并且应该出于性能原因)缓存经过身份验证的请求。解决该问题和 401 错误的简单方法是根据令牌 header 的值改变缓存。
解决方案 1.
您可以更改您的应用程序代码以简单地发送额外的 HTTP header:Vary: X-Token
。这足以指示 Varnish API.
解决方案 2.
如果你没有办法调整你的应用程序,那么一些VCL可以提供帮助:
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";
}
...
}
P.S。通常不建议将 "trailing" return
放在 vcl_recv
中,以确保 builtin vcl_recv 例程仍然 运行。