I'm confused about where to set the grace time in varnish 4. I've seen example VCL's setting the grace time in vcl_recv
sub vcl_recv {
...
set req.http.grace = 60m;
...
}
others set it in vcl_hit
sub vcl_hit {
...
set obj.grace = 60m;
...
}
and in the documentation (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-grace.html) they set in vcl_backend_response
sub vcl_backend_response {
...
set beresp.grace = 60m;
...
}
I've also seen examples where the grace time was set both in vcl_recv and vcl_backend_response.
Can anyone please explain why one would want to set it in one particular place?
In practice I want to set the grace time depending whether the backend is deemed healthy or not; intuitively I'd set it before varnish contacts the backend, so I'd set the grace time in vcl_recv and decide whether to server from cache in vcl_hit like this:
sub vcl_recv {
...
if (std.healthy(req.backend_hint)) {
set req.http.grace = 2m;
} else {
set req.http.grace = 60m;
}
...
}
sub vcl_hit {
if (obj.ttl >= 0s) {
# A standard hit, deliver from cache
return (deliver);
}
elsif (obj.ttl + obj.grace > 0s) {
# page expired, serve from cache in the meantime
return (deliver);
} else {
return (fetch);
}
}
Is this the correct approach?
This is the result of my research sofar:
My solution for having different grace times depending on the backend health is this:
Here is how my vcl_hit looks like
sub vcl_hit {
if (obj.ttl >= 0s) {
# A standard hit, deliver from cache
return (deliver);
}
elsif (std.healthy(req.backend_hint)) {
if (obj.ttl + 30m > 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);
}
}
}
Here I "defined" a 2nd grace time of 30 minutes by using the conditional
if (obj.ttl + 30m > 0s) {
In vcl_backend_response I just set the maximum grace time of 6 hours:
sub vcl_backend_response {
# define full grace time here
set beresp.grace = 6h;
...
}